Author Archives: nakulvachhrajani

Unknown's avatar

About nakulvachhrajani

Nakul Vachhrajani is a SQL Server MCTS, TOGAF certified Technical Architect with Capgemini having a total IT experience of more than 16 years. Nakul is an active blogger, and has been a guest columnist for SQLAuthority.com and SQLServerCentral.com. Nakul presented a webcast on the “Underappreciated Features of Microsoft SQL Server” at the Microsoft Virtual Tech Days Exclusive Webcast series (May 02-06, 2011) on May 06, 2011. He is also the author of a research paper on Database upgrade methodologies, which was published in a CSI journal, published nationwide. In addition to his passion about SQL Server, Nakul also contributes to the academia out of personal interest. He visits various colleges and universities as an external faculty to judge project activities being carried out by the students. Disclaimer: The opinions expressed herein are his own personal opinions and do not represent his employer’s view in anyway.

#0165-SQL Server 2012-Discontinued Features-Use of OUTER operators – *= and =*; Msg: 4147


Often, I have seen developers use code that does not conform to the ANSI standards. The reasons are many, but that is not we are discussing today. What we would discuss is that these non-standard practices need to be stopped, in some cases, by eliminating the feature all-together. The result of this effort is that the code ends up in a lot of rework because the product (in this case, Microsoft SQL Server) ends up either adopting newer standards or discontinuing support of the older, non-standardized code. 


One such coding practice is the use of non-ANSI standard OUTER operators  (*= and =*, for right outer join and left outer join respectively). Such code would typically look like:

USE Northwind
GO
SELECT EmployeeTerritories.EmployeeID,
Territories.TerritoryID,
Territories.TerritoryDescription,
Territories.RegionID
FROM EmployeeTerritories, Territories
WHERE EmployeeTerritories.TerritoryID =* Territories.TerritoryID

Output of an OUTER operator (=*) - similar to RIGHT OUTER JOIN


Effectively, the operator *= indicates that all rows from the left table need to be taken and matched with those on the right-hand side table, i.e. it is similar to a LEFT OUTER JOIN. Similarly, the operator =* is the RIGHT OUTER JOIN.


Running such code on any database with a compatibility level of 90 or higher (SQL Server 2005 or higher)  will result in the following error:


Msg 4147, Level 15, State 1, Line 3
The query uses non-ANSI outer join operators (“*=” or “=*”). To run this query without modification, please set the compatibility level for current database to 80, using the SET COMPATIBILITY_LEVEL option of ALTER DATABASE. It is strongly recommended to rewrite the query using ANSI outer join operators (LEFT OUTER JOIN, RIGHT OUTER JOIN). In the future versions of SQL Server, non-ANSI join operators will not be supported even in backward-compatibility modes.


The solution to this is to use the ANSI standard, SQL-92 syntax of LEFT and RIGHT OUTER JOIN. The query above, can therefore be represented in ANSI standard code as:

USE Northwind
GO
SELECT EmployeeTerritories.EmployeeID,
Territories.TerritoryID,
Territories.TerritoryDescription,
Territories.RegionID
FROM EmployeeTerritories
RIGHT OUTER JOIN Territories ON EmployeeTerritories.TerritoryID = Territories.TerritoryID

If yours is a product that has evolved from the days when Microsoft SQL Server was in it’s infancy, then chances are that fragments of your code still uses such non-ANSI standard code. It would be a good idea to take a couple of days to revisit the code and make it ANSI compliant to avoid further rework.


Until we meet next time,


Be courteous. Drive responsibly.

#0164-SQL Server 2012-Discontinued Features-sp_addserver-Remote server registration-Msg: 15663


In any modern day production environment, it is difficult to find an isolated instance of Microsoft SQL Server. Most enterprise class products are interfaced with different, remote systems.

In another scenario, many IT departments use pre-created images to quickly setup development and quality assurance environments. When they change the name of the server after restoring the image, the SQL Server instance name remains unchanged. In these cases, we need to rename the instance of SQL Server.

sp_addserver – Register a SQL Server instance

To register an instance of Microsoft SQL Server as a remote server to any given instance of SQL server, the system stored procedure: sp_addserver needs to be used. This system stored procedure can be used to define the name of the local or remote instance of SQL Server. Typical usage of this system stored procedure is something like the following:

--Check the instances registered with this instance of Microsoft SQL Server
--An id=0 indicates that this is a local instance
sp_helpserver
GO

--Syntax: sp_addserver 'instance name', local, duplicate_ok
--Add a remote server
sp_addserver 'WIN2K8SQL2K8'
GO

--Check the instances registered with this instance of Microsoft SQL Server
--An id=0 indicates that this is a local instance
sp_helpserver
GO

Using sp_addserver to register a remote SQL Server instance prior to SQL Server 2012

SQL Server 2012 – sp_addserver for remote servers is discontinued

Microsoft SQL Server, had a provision to add remote servers until SQL Server 2008 R2. From Microsoft SQL Server 2012, this functionality is now deprecated, and we now need to add "linked” servers instead. If a user does attempt to use the sp_addserver syntax to add a remote server, system will result in the following error:

Msg 15663, Level 16, State 1, Procedure sp_MSaddserver_internal, Line 60

Feature "sp_addserver" is no longer supported. Replace remote servers by using linked servers.

The solution is to use the sp_addlinkedserver system stored procedure, using which the script would require changes as under:

--Check the instances registered with this instance of Microsoft SQL Server
--An id=0 indicates that this is a local instance
sp_helpserver
GO

--Syntax: sp_addlinkedserver (http://msdn.microsoft.com/en-us/library/ms190479.aspx)
--Add a remote server
sp_addlinkedserver 'WIN2K8SQL2K8','SQL Server'
GO

--Check the instances registered with this instance of Microsoft SQL Server
--An id=0 indicates that this is a local instance
sp_helpserver
GO

Using sp_addlinkedserver instead of sp_addserver to register a remote SQL Server instance in SQL Server 2012

Please note that after one uses sp_addserver to rename a local instance of Microsoft SQL Server, a service restart is required for the changes to take effect.

References:

Do leave your feedback before you go. Do you use or have you ever encountered a situation where you used one of these system stored procedures? If you are an IT guy, do you ensure that your deployment strategies rename the instances of SQL Server underneath whenever you rename the host computer? Please let us know.

Until we meet next time,

Be courteous. Drive responsibly.

#0163–SQL Server 2012–Deprecated Features–Table Hint: FASTFIRSTROW-Msg: 321


Every version of SQL Server comes with a lot of optimizations to the database engine, and these changes require changes to the T-SQL syntax. New statements are introduced or modified and existing ones are dropped. Often table and query hints are optimized and modified in a similar fashion. These table and query hints are often used (in many cases, indiscriminately) to “improve the performance” of Microsoft SQL Server.


Let me start outright by saying that till date, I have never encountered the need to use the hint that we are about to discuss today.


Table v/s Query hints


Before going any further, I thought it best to revisit the simple method of identifying which is a table hint and which one is a query hint. For example, take the query below:

~~~–Query for demonstration purposes only!
USE AdventureWorks2012
GO
SELECT *
FROM HumanResources.Employee WITH (NOLOCK) — WITH (NOLOCK) is the table hint
WHERE OrganizationLevel = 3
OPTION (MAXDOP 1) — OPTION (MAXDOP 1) is the query hint~~~

The WITH (NOLOCK) hint is applied to the table/CTE/sub-query, i.e. a data source. Hence the name – table hint.


The OPTION (MAXDOP 1) is applied to the entire query, and hence the name – query hint.


[Edit]: You may also find the following post from Pinal Dave, a.k.a. “SQLAuthority” (B|T), useful in understanding Query Hints: http://blog.sqlauthority.com/2012/05/09/sql-server-quiz-and-video-introduction-to-basics-of-a-query-hint/


FASTFIRSTROW


According to SQL Server Books On Line, the FASTFIRSTROW is a table hint that helps the developer control the behaviour of the optimizer such that the optimizer,



  • Optimizes for overall minimum cost (minimum processing time/resources, etc), OR
  • Optimizes such that the time taken for the first row to be returned is minimized

The FASTFIRSTROW tells the optimizer that it is important to have the first row returned as fast as possible, allowing the application to return results to the users faster. You can see the difference by comparing the actual execution plans produced by the queries below:

~~~–Query for demonstration purposes only!
USE AdventureWorks2008
GO
–Without the table hint
SELECT *
FROM HumanResources.Employee
GO
–With the table hint
SELECT *
FROM HumanResources.Employee WITH (FASTFIRSTROW)
GO~~~

image


OPTION (FAST n)


Running the above query in SQL Server 2012 results in the following error:


Msg 321, Level 15, State 1, Line 3
“FASTFIRSTROW” is not a recognized table hints option. If it is intended as a parameter to a table-valued function or to the CHANGETABLE function, ensure that your database compatibility mode is set to 90.


The message says it all – FASTFIRSTROW is no longer available, and if you would like to use it, the database compatibility level needs to be set to 90 (i.e.  SQL Server 2005).


The replacement available is not a table hint, but a new query hint – FAST number_rows. This query hint specifies that the query is optimized for fast retrieval of the first number_rows. This is a nonnegative integer. After the first number_rows are returned, the query continues execution and produces its full result set. SQL Server 2012 has given more flexibility to the developer/administrator because the table hint only optimized for the first row, whereas the query hint allows you to specify a custom number of first rows to optimize for.


As a replacement of FASTFIRSTROW, you can use OPTION (FAST 1).

~~~–Query for demonstration purposes only!
USE AdventureWorks2012
GO
–Without the table hint
SELECT *
FROM HumanResources.Employee
GO
–With the table hint
SELECT *
FROM HumanResources.Employee
OPTION (FAST 1);
GO~~~

image


References:



Until we meet next time,


Be courteous. Drive responsibly.

#0163–SQL Server 2012–Deprecated Features–Table Hint: FASTFIRSTROW-Msg: 321


Every version of SQL Server comes with a lot of optimizations to the database engine, and these changes require changes to the T-SQL syntax. New statements are introduced or modified and existing ones are dropped. Often table and query hints are optimized and modified in a similar fashion. These table and query hints are often used (in many cases, indiscriminately) to “improve the performance” of Microsoft SQL Server.


Let me start outright by saying that till date, I have never encountered the need to use the hint that we are about to discuss today.


Table v/s Query hints


Before going any further, I thought it best to revisit the simple method of identifying which is a table hint and which one is a query hint. For example, take the query below:

--Query for demonstration purposes only!
USE AdventureWorks2012
GO
SELECT *
FROM HumanResources.Employee WITH (NOLOCK) -- WITH (NOLOCK) is the table hint
WHERE OrganizationLevel = 3
OPTION (MAXDOP 1)                          -- OPTION (MAXDOP 1) is the query hint

The WITH (NOLOCK) hint is applied to the table/CTE/sub-query, i.e. a data source. Hence the name – table hint.


The OPTION (MAXDOP 1) is applied to the entire query, and hence the name – query hint.


[Edit]: You may also find the following post from Pinal Dave, a.k.a. “SQLAuthority” (B|T), useful in understanding Query Hints: http://blog.sqlauthority.com/2012/05/09/sql-server-quiz-and-video-introduction-to-basics-of-a-query-hint/


FASTFIRSTROW


According to SQL Server Books On Line, the FASTFIRSTROW is a table hint that helps the developer control the behaviour of the optimizer such that the optimizer,



  • Optimizes for overall minimum cost (minimum processing time/resources, etc), OR
  • Optimizes such that the time taken for the first row to be returned is minimized

The FASTFIRSTROW tells the optimizer that it is important to have the first row returned as fast as possible, allowing the application to return results to the users faster. You can see the difference by comparing the actual execution plans produced by the queries below:

--Query for demonstration purposes only!
USE AdventureWorks2008
GO
--Without the table hint
SELECT *
FROM HumanResources.Employee 
GO
--With the table hint
SELECT *
FROM HumanResources.Employee WITH (FASTFIRSTROW)
GO

image


OPTION (FAST n)


Running the above query in SQL Server 2012 results in the following error:


Msg 321, Level 15, State 1, Line 3
“FASTFIRSTROW” is not a recognized table hints option. If it is intended as a parameter to a table-valued function or to the CHANGETABLE function, ensure that your database compatibility mode is set to 90.


The message says it all – FASTFIRSTROW is no longer available, and if you would like to use it, the database compatibility level needs to be set to 90 (i.e.  SQL Server 2005).


The replacement available is not a table hint, but a new query hint – FAST number_rows. This query hint specifies that the query is optimized for fast retrieval of the first number_rows. This is a nonnegative integer. After the first number_rows are returned, the query continues execution and produces its full result set. SQL Server 2012 has given more flexibility to the developer/administrator because the table hint only optimized for the first row, whereas the query hint allows you to specify a custom number of first rows to optimize for.


As a replacement of FASTFIRSTROW, you can use OPTION (FAST 1).

--Query for demonstration purposes only!
USE AdventureWorks2012
GO
--Without the table hint
SELECT *
FROM HumanResources.Employee 
GO
--With the table hint
SELECT *
FROM HumanResources.Employee
OPTION (FAST 1);
GO

image


References:



Until we meet next time,


Be courteous. Drive responsibly.

#0162–SQL Server 2012–Deprecated Features–Modify database options with sp_dboption–Msg 2812


If you have been into database administration & development for a while now, what is the first thing that comes to your mind when someone asks to modify database options like setting the database read-only, or taking it offline? Answer: The sp_dboption system stored procedure.

The typical way to modify these database options would be:

~~~–"Before" state
SELECT ‘Before’,is_read_only,state,state_desc,* FROM sys.databases db WHERE db.name = ‘TestDB’
GO
–Set the database to READ-ONLY mode
sp_dboption ‘TestDB’,’read only’,’TRUE’
GO
–"After" state
SELECT ‘Post Read Only’,is_read_only,state,state_desc,* FROM sys.databases db WHERE db.name = ‘TestDB’
GO
–Set the database OFFLINE
sp_dboption ‘TestDB’,’offline’,’TRUE’
GO
–"After" state
SELECT ‘All done’,is_read_only,state,state_desc,* FROM sys.databases db WHERE db.name = ‘TestDB’
GO~~~

image

SQL Server 2012 – Replacement – ALTER DATABASE…SET

However, starting SQL Server 2012, attempting to change the database options this way would produce the following results.

Msg 2812, Level 16, State 62, Line 1

Could not find stored procedure ‘sp_dboption’.

The system could not find the system stored procedure! That’s simply because it has been deprecated! The replacement is the ALTER DATABASE statement, and the existing sp_dboption calls need to be modified as demonstrated in the script below:

~~~–"Before" state
SELECT ‘Before’,is_read_only,state,state_desc,* FROM sys.databases db WHERE db.name = ‘TestDB’
GO
–Set the database to READ-ONLY mode
ALTER DATABASE TestDB SET READ_ONLY
GO
–"After" state
SELECT ‘Post Read Only’,is_read_only,state,state_desc,* FROM sys.databases db WHERE db.name = ‘TestDB’
GO
–Set the database OFFLINE
ALTER DATABASE TestDB SET OFFLINE
GO
–"After" state
SELECT ‘All done’,is_read_only,state,state_desc,* FROM sys.databases db WHERE db.name = ‘TestDB’
GO~~~

image

The sp_dboption system stored procedure was marked as “discontinued” ever since SQL Server 2005. Yet, I have seen  a lot of production code this year itself that uses the sp_dboption statement. All of this code will break unless it is replaced with ALTER DATABASE…SET statement.

References:

Until we meet next time,

Be courteous. Drive responsibly.