Monthly Archives: May 2011
>SQL Server: What I Have Learned in May 2011
Dedicated to Most Energetic SQL Expert Gail Shaw
SQL Tips & Tricks:
Third Party Tools:
Performance Tuning:
SQL Server Management Studio:
Database Management Views & Functions:
>SQL Server: Create/Drop Scripts for All Existing Foreign Keys
Today, when I need a script to get create and drop scripts of all existing foreign keys on a specific table (or in a whole database), I searched my query bank and find my required script quickly but on opening it I found that I was written for SQL Server 2000, time when there was no concept of schema, so I have made some changes so I can use it for SQL Server 2005 or 2008.
Create Foreign Keys:
SELECT ‘ALTER TABLE ‘ + SCHEMA_NAME(F.schema_id) + ‘.’
+ OBJECT_NAME(F.parent_object_id) + ‘ ADD CONSTRAINT ‘ + F.name
+ ‘ FOREIGN KEY ‘ + ‘(‘ + COL_NAME(FC.parent_object_id,
FC.parent_column_id) + ‘)’
+ ‘ REFERENCES ‘ + SCHEMA_NAME(RefObj.schema_id) + ‘.’
+ OBJECT_NAME(F.referenced_object_id) + ‘ (‘
+ COL_NAME(FC.referenced_object_id, FC.referenced_column_id) + ‘)’
FROM SYS.FOREIGN_KEYS AS F
INNER JOIN SYS.FOREIGN_KEY_COLUMNS AS FC ON F.OBJECT_ID = FC.constraint_object_id
INNER JOIN sys.objects RefObj ON RefObj.object_id = f.referenced_object_id
–WHERE OBJECT_NAME(F.PARENT_OBJECT_ID) = ‘YourObjectName’
Drop Foreign Keys
SELECT ‘ALTER TABLE ‘ + SCHEMA_NAME(F.schema_id) + ‘.’
+ OBJECT_NAME(F.parent_object_id) + ‘ DROP CONSTRAINT ‘ + F.name
FROM SYS.FOREIGN_KEYS AS F
INNER JOIN SYS.FOREIGN_KEY_COLUMNS AS FC ON F.OBJECT_ID = FC.constraint_object_id
–WHERE OBJECT_NAME(F.PARENT_OBJECT_ID) = ‘YourObjectName’
SQL Server: Shortcuts for TSQL Code in SSMS
For a developer or DBA it’s common to start their day with “SELECT * FROM” and in a daily routine work we type same lines of script many times. If you are a lazy developer or DBA like me then sometime it feels boring to type same code again and again. Intellisence in SQL Server 2008, saved lot of time but still it lacks few features, which other third party tools were offering before SQL Server 2008. Through such tools like SQL PROMPT, we have ability to type shortcuts in editor which after pressing Enter or Tab turn into a predefined code block. Like I will just type * and it will convert it to “SELECT * FROM”.
If you don’t like to purchase these tools but still want to make your life easy then you need SSMS Tools by Mladen Prajdić, totally free and you can download from here. Beside other good tools it has an option of SQL Snippets. Although it already have a good list of shortcuts but still you can add of your choice.
SSC = SELECT COUNT(*) FROM
SSF = SELECT * FROM
UPD = UPDATE <>
SET <>
FROM <>
>SQL Server: Column Value with Leading Zeros
>
Till date I was using old CASE option to add zeros before a digit to get all values with same length for columns like social security number but today SQL Expert Shakeeb Younas shared a very simple method to achieve above mentioned goal.
DECLARE @Emp TABLE ( SSN VARCHAR(9) )
INSERT INTO @Emp
SELECT ‘1’
UNION ALL
SELECT ‘654’
UNION ALL
SELECT ‘824741’
UNION ALL
SELECT ‘123456789’
UNION ALL
SELECT ’37’
— Get SSN with leading zeros
SELECT REPLACE(STR(SSN, 9), ‘ ‘, ‘0’) AS SSN
FROM @Emp
>SQL Server: Which Performs Better, IN or EXISTS
>
It’s true that to solve a problem in TSQL you have many choices, and adopting any of these techniques you can get your desired results. Today we will discuss two very commonly used IN and EXISTS clause to filter query result set based on records from a sub-query. As compared to EXISTS, IN is more commonly used, but which one is more efficient? That’s what we are looking for, today.
IN and EXISTS perform in a same way if we use them with single column search. Like as follow:
USE AdventureWorks
GO
–IN
SELECT * FROM Production.Product pr
WHERE ProductID IN
(SELECT ProductID FROM Purchasing.ProductVendor)
–EXISTS
SELECT * FROM Production.Product pr
WHERE EXISTS
(SELECT 1 FROM Purchasing.ProductVendor
WHERE ProductID = pr.ProductID)
WHERE ProductID = pr.ProductID)
Logical reads and query elapsed time is also same for both queries.
In situations where you need to filter records based on more than one columns existence in sub-query, you will find EXISTS much better in performance. To observe this, let’s create two temporary tables.
CREATE TABLE #Cars (Make VARCHAR(50), Color VARCHAR(30), Seats INT)
CREATE TABLE #CarIssuance (Make VARCHAR(50),Color VARCHAR(30),IssuanceDate DATETIME)
GO
INSERT INTO #Cars
SELECT ‘Honda’,‘Black’,2 union all
SELECT ‘Honda’,‘White’,2 union all
SELECT ‘Toyota‘,‘Black’,4 union all
SELECT ‘Toyota‘,‘Silver’,4 union all
SELECT ‘BMW’, ‘Red’,2
GO
INSERT INTO #CarIssuance
SELECT ‘Honda’,‘Black’,‘2011-05-20’ union all
SELECT ‘BMW’,‘Red’,‘2011-05-03’ union all
SELECT ‘Toyota‘,‘Black’,‘2011-05-03’
If we need to get all records from #Cars table, where records exists in #CarIssuance table on basis of “make” and “color” columns. Let’s first try traditional IN clause.
SELECT * FROM #Cars
WHERE Color IN
(SELECT Color FROM #CarIssuance)
AND Make IN
(SELECT Make FROM #CarIssuance)
Table ‘#CarIssuance Scan count 2, logical reads 8, physical reads 0, read-ahead reads 0
Table ‘#Cars Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 40 ms.
Now execute same query with EXISTS option
SELECT * FROM #Cars Cr
WHERE
EXISTS
(SELECT 1 FROM #CarIssuance CI
WHERE Make = Cr.Make
AND Color = Cr.Color)
Table ‘#CarIssuance Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0
Table ‘#Cars Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 1 ms.
Exists performed much better (We got result in 1ms instead of 40ms) just because we have used single sub-query but in case of “IN”, we have used multiple sub-queries. So if somehow, we change our first query of “IN” clause so that we can use only one sub-query, performance will be same as to EXISTS. But code will be bit mixed up and in real life sometime even its not possible.
SELECT * FROM #Cars Cr
WHERE Color IN
(SELECT Color FROM #CarIssuance WHERE Make = Cr.Make)
Summary: Exists performs much better when used for more then one column filter from a sub-query but as a good programming practice EXISTS must be preferred even when handling with single column filter.
>SQL Server: How to Remove Special Characters
>
One more useful function from my query bank, which I like to use to remove special characters from a string.
CREATE FUNCTION dbo.RemoveSpecialChars ( @InputString VARCHAR(8000) )
RETURNS VARCHAR(8000)
BEGIN
IF @InputString IS NULL
RETURN NULL
DECLARE @OutputString VARCHAR(8000)
SET @OutputString = ”
DECLARE @l INT
SET @l = LEN(@InputString)
DECLARE @p INT
SET @p = 1
WHILE @p <= @l
BEGIN
DECLARE @c INT
SET @c = ASCII(SUBSTRING(@InputString, @p, 1))
IF @c BETWEEN 48 AND 57
OR @c BETWEEN 65 AND 90
OR @c BETWEEN 97 AND 122
–OR @c = 32
SET @OutputString = @OutputString + CHAR(@c)
SET @p = @p + 1
END
IF LEN(@OutputString) = 0
RETURN NULL
RETURN @OutputString
END
How to use it.
SELECT dbo.RemoveSpecialChars (‘This string contains special chracters:/ Which * & we % need @ to #remove’)
According to this function space is a special character and if you want to ignore spaces then uncomment “OR @c = 32”.
>SQL Server: How to Remove Extra Spaces From String Value
>
Extra spaces between characters of a string value is a common problem and if you’re a developer then you must have faced the problem. On request of a blog reader here is a script from my query bank which I like to use to remove such extra spaces.
–Create a temp table for testing our query
CREATE TABLE #ExtraSpaces ( MyVal VARCHAR(8000))
–Insert some value to test
INSERT INTO #ExtraSpaces
SELECT ‘This is my message. ‘
UNION ALL
SELECT ‘This message contains tabs and extra spaces’
— Lets remove extra spaces and tabs
WHILE 1 = 1
BEGIN
UPDATE #ExtraSpaces
SET MyVal = REPLACE(
SUBSTRING(MyVal, 1,
CHARINDEX(‘ ‘, MyVal, 1) – 1) + ‘ ‘
+ LTRIM(
SUBSTRING(MyVal,
CHARINDEX(‘ ‘, MyVal, 1), 8000)),‘ ‘,‘ ‘)
WHERE CHARINDEX(‘ ‘, MyVal, 1) > 0
IF @@rowcount = 0
BREAK
END
–Lets see the updated result
SELECT MyVal FROM #ExtraSpaces
–drop temp table when not required
DROP TABLE #ExtraSpaces
SQL Server: Query Template, a Time Saving Feature
While working with SQL Server, its common to have a saved script which you need to execute for different server or databases and usually you open this saved script, make changes according to requirements and execute. SQL Server 2008 has one more time saving facility. You can save your script as template, like following is a simple query script, which I like to execute for different databases and with different order by clause.
>SQL Server: Query Template, a Time Saving Feature
>
While working with SQL Server, its common to have a saved script which you need to execute for different server or databases and usually you open this saved script, make changes according to requirements and execute. SQL Server 2008 has one more time saving facility. You can save your script as template, like following is a simple query script, which I like to execute for different databases and with different order by clause.
USE AdventureWorks
GO
SELECT s.SalesPersonID, c.Title, c.FirstName,
c.MiddleName, c.LastName, c.Suffix,e.Title AS JobTitle,s.SalesQuota, s.SalesYTD
FROM Sales.SalesPerson AS s INNER JOIN
HumanResources.Employee AS e
ON e.EmployeeID = s.SalesPersonID
LEFT OUTER JOIN
Sales.SalesTerritory AS st
ON st.TerritoryID = s.TerritoryID
INNER JOIN
Person.Contact AS c
ON c.ContactID = e.ContactID
ORDER BY c.FirstName
One solution to avoid any labor work to change above script manually according to my requirements, is to create a dynamic query. But, in SQL Server 2008 I would prefer Query Template, by saving above query in following Template.
USE
GO
SELECT s.SalesPersonID, c.Title, c.FirstName,
c.MiddleName, c.LastName,
c.Suffix,e.Title AS JobTitle,s.SalesQuota, s.SalesYTD
FROM Sales.SalesPerson AS s INNER JOIN
HumanResources.Employee AS e
ON e.EmployeeID = s.SalesPersonID
LEFT OUTER JOIN
Sales.SalesTerritory AS st
ON st.TerritoryID = s.TerritoryID
INNER JOIN
Person.Contact AS c
ON c.ContactID = e.ContactID
ORDER BY
Next time when I need to execute this script, I will just open the template and press Ctlr+Shift+M or click on replace button, and it will ask me for template parameters value and on pressing OK button it will replace template parameters with my values on whole script.
Defining a template needs three parameters separated with comma and enclosed with < and > signs.
<TemplateParameter, ParameterDataType, DefaultValue>
Replace Button
>SQL Server: sp_WhoIsActive, a Must Tool for a DBA
>
A mail with subject “Low Database Response” or a call with words “What happened to the database?” is normal in a SQL Server DBA’s life. To cope with such bad situations normally a DBA keeps his drawer filled with necessary tools and scripts. But like me, most of DBAs first query to check “What is happening actually” is shortest query in SQL Server i.e. sp_who or sp_who2. Second returns almost same data to sp_who but with more detail information.
sp_who
sp_who2
Though both system stored procedures are helpful to collect basic information to find out problematic sessions of database but to reach your desired rows, you have to skim through large number of rows and you will find more then 95% of rows useless. Some time information provided by sp_who or sp_who2 is not enough to understand the real problem which leads you to query some other DMVs for such information.
Thanks to Adam Machanic who resolved this problem. His stored procedure WhoIsActive is a must tool for a DBAs kit. This single stored procedure collects almost all necessary information for a DBA, which will be helpful to understand the real problem of a database. The beauty of this stored procedure is that it collects information using almost 15 DMVs but still returns only necessary rows.