I have answered a bunch of questions over the last couple of days and some of them had to do with returning values from stored procedures
Everyone knows that you can return a value by using return inside a stored procedure. What everyone doesn't know is that return can only be an int data type
So how do you return something that is not an int (bigint, smallint etc etc) datatype
Let's take a look
We will start with a regular return statement, everything works as expected
--#1 return
CREATE PROCEDURE TestReturn
AS
SET NOCOUNT ON
DECLARE @i int
SELECT @i = DATEPART(hh,GETDATE())
RETURN @i
SET NOCOUNT OFF
GO
DECLARE @SomeValue int
EXEC @SomeValue = TestReturn
SELECT @SomeValue
GO
Now let's try returning a varchar
ALTER PROCEDURE TestReturn
AS
SET NOCOUNT ON
DECLARE @i VARCHAR(50)
SELECT @i = DATENAME(mm,GETDATE())
RETURN @i
SET NOCOUNT OFF
GO
DECLARE @SomeValue VARCHAR(50)
EXEC @SomeValue = TestReturn
SELECT @SomeValue
GO
Oops, it doesn't work the following message is returned (if you run it in September)
Server: Msg 245, Level 16, State 1, Procedure TestReturn, Line 7
Syntax error converting the varchar value 'September' to a column of data type int.
Let's try hard coding a character value
ALTER PROCEDURE TestReturn
AS
SET NOCOUNT ON
RETURN 'ab'
SET NOCOUNT OFF
GO
DECLARE @SomeValue VARCHAR(50)
EXEC @SomeValue = TestReturn
SELECT @SomeValue
GO
It is interesting that the procedure compiles without a problem. But when we try to run it the following message is displayed
Server: Msg 245, Level 16, State 1, Procedure TestReturn, Line 7
Syntax error converting the varchar value 'ab' to a column of data type int.
So what can we do? well we can use an OUTPUT parameter. By the way the following 4 ways to return a varchar values are in the order from best to worst
--#2 OUTPUT
ALTER PROCEDURE TestReturn @SomeParm VARCHAR(50) OUTPUT
AS
SET NOCOUNT ON
SELECT @SomeParm = 'ab'
SET NOCOUNT OFF
GO
DECLARE @SomeValue VARCHAR(50)
EXEC TestReturn @SomeParm = @SomeValue OUTPUT
SELECT @SomeValue
GO
Another way is to create a temp table and call the proc with insert..exec
--#3 Insert Into TEMP Table outside the proc
ALTER PROCEDURE TestReturn
AS
SET NOCOUNT ON
SELECT 'ab'
SET NOCOUNT OFF
GO
DECLARE @SomeValue VARCHAR(50)
CREATE TABLE #Test(SomeValue VARCHAR(50))
INSERT INTO #Test
EXEC TestReturn
SELECT @SomeValue = SomeValue
FROM #Test
SELECT @SomeValue
DROP TABLE #Test
GO
This one is almost the same as the previous example, the only difference is that ther insert happens inside the proc
And of course if you call the proc without creating the table you will get a nice error message
--#4 Insert Into TEMP Table inside the proc
ALTER PROCEDURE TestReturn
AS
SET NOCOUNT ON
INSERT INTO #Test
SELECT 'ab'
SET NOCOUNT OFF
GO
DECLARE @SomeValue VARCHAR(50)
CREATE TABLE #Test(SomeValue VARCHAR(50))
EXEC TestReturn
SELECT @SomeValue = SomeValue
FROM #Test
SELECT @SomeValue
DROP TABLE #Test
And last you create a permanent table with an identity, in the proc you insert into that table and you return the identity value. You can then use that identity value to get the varchar value
--#5 Insert Into A Table And Return The Identity value
CREATE TABLE HoldingTable(ID INT IDENTITY,SomeValue VARCHAR(50))
GO
ALTER PROCEDURE TestReturn
AS
SET NOCOUNT ON
DECLARE @i INT
INSERT INTO HoldingTable
SELECT 'ab'
SELECT @I = SCOPE_IDENTITY()
RETURN @i
SET NOCOUNT OFF
GO
DECLARE @SomeValue VARCHAR(50), @i INT
EXEC @i = TestReturn
SELECT @SomeValue = SomeValue
FROM HoldingTable
WHERE ID = @i
SELECT @SomeValue
DROP PROCEDURE TestReturn
A blog about SQL Server, Books, Movies and life in general
Wednesday, September 20, 2006
Tuesday, September 19, 2006
You Can Rollback Tables That You Have Truncated (Inside A Transaction)
There seems to be a misconception that when you issue a TRUNCATE command against a table you will not be able to roll back.
That simply is not true; TRUNCATE TABLE removes the data by deallocating the data pages used to store the table's data, and only the page deallocations are recorded in the transaction log.
What does this mean? This means that SQL Server will use the mimimum amount of logging that it can to delete the data and still make it recoverable. in contrast to that the DELETE statement removes rows one at a time and records an entry in the transaction log for each deleted row
You see why TRUNCATE is so much faster; it deals with pages not with rows. and we all know that 1 extent is 8 pages and a page is 8K and can hold 8060 bytes. Well if you rows are 20 bytes wide then you need to log 403 delete statements with DELETE but TRUNCATE just uses a pointer to the page
So let's see how that works
--Create the table and inser 6 values
CREATE TABLE RollBacktest(id INT)
INSERT RollBacktest VALUES( 1 )
INSERT RollBacktest VALUES( 2 )
INSERT RollBacktest VALUES( 3 )
INSERT RollBacktest VALUES( 4 )
INSERT RollBacktest VALUES( 5 )
INSERT RollBacktest VALUES( 6 )
GO
--Should be 6 rows
SELECT 'Before The Transaction',* FROM RollBacktest
BEGIN TRAN RollBackTestTran
TRUNCATE TABLE RollBacktest
--Should be empty resultset
SELECT * FROM RollBacktest
--should be 0
SELECT COUNT(*) AS 'TruncatedCount' FROM RollBacktest
ROLLBACK TRAN RollBackTestTran
--Yes it is 6 again
SELECT 'ROLLED BACK',* FROM RollBacktest
DROP TABLE RollBacktest
That simply is not true; TRUNCATE TABLE removes the data by deallocating the data pages used to store the table's data, and only the page deallocations are recorded in the transaction log.
What does this mean? This means that SQL Server will use the mimimum amount of logging that it can to delete the data and still make it recoverable. in contrast to that the DELETE statement removes rows one at a time and records an entry in the transaction log for each deleted row
You see why TRUNCATE is so much faster; it deals with pages not with rows. and we all know that 1 extent is 8 pages and a page is 8K and can hold 8060 bytes. Well if you rows are 20 bytes wide then you need to log 403 delete statements with DELETE but TRUNCATE just uses a pointer to the page
So let's see how that works
--Create the table and inser 6 values
CREATE TABLE RollBacktest(id INT)
INSERT RollBacktest VALUES( 1 )
INSERT RollBacktest VALUES( 2 )
INSERT RollBacktest VALUES( 3 )
INSERT RollBacktest VALUES( 4 )
INSERT RollBacktest VALUES( 5 )
INSERT RollBacktest VALUES( 6 )
GO
--Should be 6 rows
SELECT 'Before The Transaction',* FROM RollBacktest
BEGIN TRAN RollBackTestTran
TRUNCATE TABLE RollBacktest
--Should be empty resultset
SELECT * FROM RollBacktest
--should be 0
SELECT COUNT(*) AS 'TruncatedCount' FROM RollBacktest
ROLLBACK TRAN RollBackTestTran
--Yes it is 6 again
SELECT 'ROLLED BACK',* FROM RollBacktest
DROP TABLE RollBacktest
Monday, September 18, 2006
DDL Trigger Events Documented In Books On Line
A while back I wrote about DDL trigger events in a post named DDL Trigger Events Revisited
And I claimed that this stuff wasn't documented
Well I am wrong, this information is documented in the Books Online topic "Event Groups for Use with DDL Triggers.
The link to the online Books On Line is below
http://msdn2.microsoft.com/en-us/library/ms191441.aspx
Anyway they have an image, at least you can copy and paste the code I gave you ;-)
And I claimed that this stuff wasn't documented
Well I am wrong, this information is documented in the Books Online topic "Event Groups for Use with DDL Triggers.
The link to the online Books On Line is below
http://msdn2.microsoft.com/en-us/library/ms191441.aspx
Anyway they have an image, at least you can copy and paste the code I gave you ;-)
Friday, September 15, 2006
Do Not Concatenate VARCHAR and VARCHAR(MAX) Variables
Do Not Concatenate VARCHAR and VARCHAR(MAX) Variables, what happens is that the whole string will be implicitly converted to varchar(8000)
Run these examples to see what I mean
declare @v varchar(max)
select @v = (cast('a' as varchar)) + replicate('a', 9000)
select len(@v)
--8000
GO
declare @v varchar(max)
select @v = (cast('a' as varchar(1))) + replicate('a', 9000)
select len(@v)
--8000
GO
declare @v varchar(max)
select @v = (cast('a' as varchar)) +replicate (cast('a' as varchar(max)), 9000)
select len(@v)
--9001
GO
declare @v varchar(max)
select @v = (cast('a' as varchar(1))) + replicate(cast('a' as varchar(max)), 9000)
select len(@v)
--9001
GO
Or how about this? If you don't convert to varchar(max) while doing the LEN function it returns 8000
declare @v varchar(max)
select @v = replicate('a', 9000)
select len(@v)
declare @v varchar(max)
select @v = replicate(cast('a' as varchar(max)), 9000)
select len(@v)
Run these examples to see what I mean
declare @v varchar(max)
select @v = (cast('a' as varchar)) + replicate('a', 9000)
select len(@v)
--8000
GO
declare @v varchar(max)
select @v = (cast('a' as varchar(1))) + replicate('a', 9000)
select len(@v)
--8000
GO
declare @v varchar(max)
select @v = (cast('a' as varchar)) +replicate (cast('a' as varchar(max)), 9000)
select len(@v)
--9001
GO
declare @v varchar(max)
select @v = (cast('a' as varchar(1))) + replicate(cast('a' as varchar(max)), 9000)
select len(@v)
--9001
GO
Or how about this? If you don't convert to varchar(max) while doing the LEN function it returns 8000
declare @v varchar(max)
select @v = replicate('a', 9000)
select len(@v)
declare @v varchar(max)
select @v = replicate(cast('a' as varchar(max)), 9000)
select len(@v)
Thursday, September 14, 2006
O'Reilly Code Search
Here is something handy:
Announcing O'Reilly Code Search, where you can enter search terms to find relevant sample code from nearly 700 O'Reilly books. The database currently contains over 123,000 individual examples, comprises 2.6 million lines of code, all edited and ready to use.
it's pretty neat, all the source code from all the O'Reilly books is searchable online
So to Search for the term SELECT in category SQL you would enter "cat:sql select" and this would return these results http://labs.oreilly.com/search.xqy?t=code&q=cat%3Asql+select
For C# you would do "cat:csharp select" and just SQL Server instead of SQL would be "cat:sql server select"
Let me know what you think
Announcing O'Reilly Code Search, where you can enter search terms to find relevant sample code from nearly 700 O'Reilly books. The database currently contains over 123,000 individual examples, comprises 2.6 million lines of code, all edited and ready to use.
it's pretty neat, all the source code from all the O'Reilly books is searchable online
So to Search for the term SELECT in category SQL you would enter "cat:sql select" and this would return these results http://labs.oreilly.com/search.xqy?t=code&q=cat%3Asql+select
For C# you would do "cat:csharp select" and just SQL Server instead of SQL would be "cat:sql server select"
Let me know what you think
Wednesday, September 13, 2006
What Is Your Corporate Standard
If you are not a consultant and you work for a company then does your company have a corporate standard for development languages/products?
Our IT department is about 800 people and to get good support you can not have 3 thousands different products in your shop. As of today this is what is supported in our company
Java Stack
Sun's Project Tango
Apache Web Server 2.x
Tomcat 5.x (web container), JBoss 4.x (EJB and Web Container), WebSphere Network Edition 6.1.x (web and EJB container)
Hibernate 2.x, Spring 1.2.x
Sun's J2SE 5 (aka J2SE 1.5.x)
MySQl 5.x, Oracle 10g, SQL Server 2005
.NET Stack
WCF
IIS 6
.NET 2.0
CLR Version 2
MySQl 5.x, Oracle 10g, SQL Server 2005
Of course we have other things that we use ColdFusion, SQL Server 2000, that is fine but no NEW development is supposed to be done with those tools/products
So here is my question to you; what is your corporate standard?
Our IT department is about 800 people and to get good support you can not have 3 thousands different products in your shop. As of today this is what is supported in our company
Java Stack
Sun's Project Tango
Apache Web Server 2.x
Tomcat 5.x (web container), JBoss 4.x (EJB and Web Container), WebSphere Network Edition 6.1.x (web and EJB container)
Hibernate 2.x, Spring 1.2.x
Sun's J2SE 5 (aka J2SE 1.5.x)
MySQl 5.x, Oracle 10g, SQL Server 2005
.NET Stack
WCF
IIS 6
.NET 2.0
CLR Version 2
MySQl 5.x, Oracle 10g, SQL Server 2005
Of course we have other things that we use ColdFusion, SQL Server 2000, that is fine but no NEW development is supposed to be done with those tools/products
So here is my question to you; what is your corporate standard?
The sum or average aggregate operation cannot take a bit data type as an argument
The sum or average aggregate operation cannot take a bit data type as an argument.
Oh yes I fell for this one yesterday. It's not that I didn't know about it (in the back of my head) it's just that I forgot
I was answering one question in the microsoft forums and someone wanted to sum something, unfortunately the datatype was bit and as we all know bit data types can not be used with average or sum.
You see that's why it is important when asking question to provide DDL and INSERT scripts. If I had that then I would have gotten the error myself and would have modified the query by converting to int
So instead of this (simplified)
SELECT SUM(col1)
FROM (SELECT CONVERT(BIT,1) AS col1 UNION ALL
SELECT CONVERT(BIT,0) )P
I would have done this
SELECT SUM(CONVERT(INT,col1))
FROM (SELECT CONVERT(BIT,1) AS col1 UNION ALL
SELECT CONVERT(BIT,0) )P
And of course we should all read this-->
http://classicasp.aspfaq.com/general/how-do-i-make-sure-my-asp-question-gets-answered.htm l
Does this qualify as a rant? I hope not.
Oh yes I fell for this one yesterday. It's not that I didn't know about it (in the back of my head) it's just that I forgot
I was answering one question in the microsoft forums and someone wanted to sum something, unfortunately the datatype was bit and as we all know bit data types can not be used with average or sum.
You see that's why it is important when asking question to provide DDL and INSERT scripts. If I had that then I would have gotten the error myself and would have modified the query by converting to int
So instead of this (simplified)
SELECT SUM(col1)
FROM (SELECT CONVERT(BIT,1) AS col1 UNION ALL
SELECT CONVERT(BIT,0) )P
I would have done this
SELECT SUM(CONVERT(INT,col1))
FROM (SELECT CONVERT(BIT,1) AS col1 UNION ALL
SELECT CONVERT(BIT,0) )P
And of course we should all read this-->
http://classicasp.aspfaq.com/general/how-do-i-make-sure-my-asp-question-gets-answered.htm l
Does this qualify as a rant? I hope not.
Sunday, September 10, 2006
sys.dm_db_index_usage_stats
This is the second article about the dynamic managment views in SQL Server 2005, to see all of them click here
Today we are going to talk about the sys.dm_db_index_usage_stats dynamic managment view
This view is extremely helpful in a couple of ways, I will list some of them
It can help you identify if an index is used or not
You can also find out the scan to seek ratio
Another helpful thing is the fact that the last seek and scan dates are in the view, this can help you determine if the index is still used
So let's get started shall we?
CREATE TABLE TestIndex(id INT identity,
SomeID INT not null,
SomeDate DATETIME not null)
GO
CREATE CLUSTERED INDEX IX_TestIndexID ON TestIndex(SomeID)
GO
CREATE NONCLUSTERED INDEX IX_TestIndexDate ON TestIndex(SomeDate)
GO
INSERT TestIndex VALUES(1,GETDATE())
GO
INSERT TestIndex VALUES(2,GETDATE()-1)
GO
--Run the sys.dm_db_index_usage_stats query
SELECT
TableName = OBJECT_NAME(s.[object_id]),
IndexName = i.name,
s.last_user_seek,
s.user_seeks,
CASE s.user_seeks WHEN 0 THEN 0
ELSE s.user_seeks*1.0 /(s.user_scans + s.user_seeks) * 100.0 END AS SeekPercentage,
s.last_user_scan,
s.user_scans,
CASE s.user_scans WHEN 0 THEN 0
ELSE s.user_scans*1.0 /(s.user_scans + s.user_seeks) * 100.0 END AS ScanPercentage,
s.last_user_lookup,
s.user_lookups,
s.last_user_update,
s.user_updates,
s.last_system_seek,
s.last_system_scan,
s.last_system_lookup,
s.last_system_update,*
FROM
sys.dm_db_index_usage_stats s
INNER JOIN
sys.indexes i
ON
s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
WHERE
s.database_id = DB_ID()
AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0
AND OBJECT_NAME(s.[object_id]) = 'TestIndex';
After each of the select queries below run the sys.dm_db_index_usage_stats query above
--user_updates should be 2 but user_seeks,user_scans, user_lookups should be 0
SELECT *
FROM TestIndex
WHERE ID =1
--IX_TestIndexID user_scans = 1
SELECT *
FROM TestIndex
WHERE SomeID =1
--IX_TestIndexID user_seeks = 1
SELECT *
FROM TestIndex
WHERE SomeDate > GETDATE() -1
AND SomeID =1
--IX_TestIndexID user_seeks = 2
--let's force the optimizer to use the IX_TestIndexDate index
SELECT *
FROM TestIndex WITH (INDEX = IX_TestIndexDate)
WHERE SomeDAte > GETDATE() -1
--IX_TestIndexDate user_seeks = 1
IX_TestIndexID
SeekPercentage = 66.66% and ScanPercentage = 33.33
As you can see I have added the following code
CASE s.user_seeks WHEN 0 THEN 0
ELSE s.user_seeks*1.0 /(s.user_scans + s.user_seeks) * 100.0 END AS SeekPercentage
CASE s.user_scans WHEN 0 THEN 0
ELSE s.user_scans*1.0 /(s.user_scans + s.user_seeks) * 100.0 END AS ScanPercentage
This is helpful to determine the seek/scan ratio if you have mostly scans then maybe you have to look at your queries to optimize them
If you run the sys.dm_db_index_usage_stats query again you will se that the user_updates column is 2, that's because we inserted 2 rows (2 batches)
Let's do this
UPDATE TestIndex
SET SomeID = SomeID + 1
--(2 row(s) affected)
Now user_updates is 3 since we used 1 batch that modified 2 rows
Now restart your server and run the same query again. as you can see the resultset is empty this is because the counters are initialized to empty whenever the SQL Server (MSSQLSERVER) service is started. In addition, whenever a database is detached or is shut down (for example, because AUTO_CLOSE is set to ON), all rows associated with the database are removed.
When an index is used, a row is added to sys.dm_db_index_usage_stats if a row does not already exist for the index. When the row is added, its counters are initially set to zero.
When you run this query
SELECT *
FROM TestIndex
You will see a row again after you run the sys.dm_db_index_usage_stats query
Also note that every individual seek, scan, lookup, or update on the specified index by one query execution is counted as a use of that index and increments the corresponding counter in this view. Information is reported both for operations caused by user-submitted queries, and for operations caused by internally generated queries, such as scans for gathering statistics.
The user_updates counter indicates the level of maintenance on the index caused by insert, update, or delete operations on the underlying table or view. You can use this view to determine which indexes are used only lightly all by your applications. You can also use the view to determine which indexes are incurring maintenance overhead. You may want to consider dropping indexes that incur maintenance overhead, but are not used for queries, or are only infrequently used for queries.
sys.dm_db_index_usage_stats
database_id smallint
ID of the database on which the table or view is defined.
object_id int
ID of the table or view on which the index is defined
index_id int
ID of the index.
user_seeks bigint
Number of seeks by user queries.
user_scans bigint
Number of scans by user queries.
user_lookups bigint
Number of lookups by user queries.
user_updates bigint
Number of updates by user queries.
last_user_seek datetime
Time of last user seek
last_user_scan datetime
Time of last user scan.
last_user_lookup datetime
Time of last user lookup.
last_user_update datetime
Time of last user update.
system_seeks bigint
Number of seeks by system queries.
system_scans bigint
Number of scans by system queries.
system_lookups bigint
Number of lookups by system queries.
system_updates bigint
Number of updates by system queries.
last_system_seek datetime
Time of last system seek.
last_system_scan datetime
Time of last system scan.
last_system_lookup datetime
Time of last system lookup.
last_system_update datetime
Time of last system update.
Today we are going to talk about the sys.dm_db_index_usage_stats dynamic managment view
This view is extremely helpful in a couple of ways, I will list some of them
It can help you identify if an index is used or not
You can also find out the scan to seek ratio
Another helpful thing is the fact that the last seek and scan dates are in the view, this can help you determine if the index is still used
So let's get started shall we?
CREATE TABLE TestIndex(id INT identity,
SomeID INT not null,
SomeDate DATETIME not null)
GO
CREATE CLUSTERED INDEX IX_TestIndexID ON TestIndex(SomeID)
GO
CREATE NONCLUSTERED INDEX IX_TestIndexDate ON TestIndex(SomeDate)
GO
INSERT TestIndex VALUES(1,GETDATE())
GO
INSERT TestIndex VALUES(2,GETDATE()-1)
GO
--Run the sys.dm_db_index_usage_stats query
SELECT
TableName = OBJECT_NAME(s.[object_id]),
IndexName = i.name,
s.last_user_seek,
s.user_seeks,
CASE s.user_seeks WHEN 0 THEN 0
ELSE s.user_seeks*1.0 /(s.user_scans + s.user_seeks) * 100.0 END AS SeekPercentage,
s.last_user_scan,
s.user_scans,
CASE s.user_scans WHEN 0 THEN 0
ELSE s.user_scans*1.0 /(s.user_scans + s.user_seeks) * 100.0 END AS ScanPercentage,
s.last_user_lookup,
s.user_lookups,
s.last_user_update,
s.user_updates,
s.last_system_seek,
s.last_system_scan,
s.last_system_lookup,
s.last_system_update,*
FROM
sys.dm_db_index_usage_stats s
INNER JOIN
sys.indexes i
ON
s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
WHERE
s.database_id = DB_ID()
AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0
AND OBJECT_NAME(s.[object_id]) = 'TestIndex';
After each of the select queries below run the sys.dm_db_index_usage_stats query above
--user_updates should be 2 but user_seeks,user_scans, user_lookups should be 0
SELECT *
FROM TestIndex
WHERE ID =1
--IX_TestIndexID user_scans = 1
SELECT *
FROM TestIndex
WHERE SomeID =1
--IX_TestIndexID user_seeks = 1
SELECT *
FROM TestIndex
WHERE SomeDate > GETDATE() -1
AND SomeID =1
--IX_TestIndexID user_seeks = 2
--let's force the optimizer to use the IX_TestIndexDate index
SELECT *
FROM TestIndex WITH (INDEX = IX_TestIndexDate)
WHERE SomeDAte > GETDATE() -1
--IX_TestIndexDate user_seeks = 1
IX_TestIndexID
SeekPercentage = 66.66% and ScanPercentage = 33.33
As you can see I have added the following code
CASE s.user_seeks WHEN 0 THEN 0
ELSE s.user_seeks*1.0 /(s.user_scans + s.user_seeks) * 100.0 END AS SeekPercentage
CASE s.user_scans WHEN 0 THEN 0
ELSE s.user_scans*1.0 /(s.user_scans + s.user_seeks) * 100.0 END AS ScanPercentage
This is helpful to determine the seek/scan ratio if you have mostly scans then maybe you have to look at your queries to optimize them
If you run the sys.dm_db_index_usage_stats query again you will se that the user_updates column is 2, that's because we inserted 2 rows (2 batches)
Let's do this
UPDATE TestIndex
SET SomeID = SomeID + 1
--(2 row(s) affected)
Now user_updates is 3 since we used 1 batch that modified 2 rows
Now restart your server and run the same query again. as you can see the resultset is empty this is because the counters are initialized to empty whenever the SQL Server (MSSQLSERVER) service is started. In addition, whenever a database is detached or is shut down (for example, because AUTO_CLOSE is set to ON), all rows associated with the database are removed.
When an index is used, a row is added to sys.dm_db_index_usage_stats if a row does not already exist for the index. When the row is added, its counters are initially set to zero.
When you run this query
SELECT *
FROM TestIndex
You will see a row again after you run the sys.dm_db_index_usage_stats query
Also note that every individual seek, scan, lookup, or update on the specified index by one query execution is counted as a use of that index and increments the corresponding counter in this view. Information is reported both for operations caused by user-submitted queries, and for operations caused by internally generated queries, such as scans for gathering statistics.
The user_updates counter indicates the level of maintenance on the index caused by insert, update, or delete operations on the underlying table or view. You can use this view to determine which indexes are used only lightly all by your applications. You can also use the view to determine which indexes are incurring maintenance overhead. You may want to consider dropping indexes that incur maintenance overhead, but are not used for queries, or are only infrequently used for queries.
sys.dm_db_index_usage_stats
database_id smallint
ID of the database on which the table or view is defined.
object_id int
ID of the table or view on which the index is defined
index_id int
ID of the index.
user_seeks bigint
Number of seeks by user queries.
user_scans bigint
Number of scans by user queries.
user_lookups bigint
Number of lookups by user queries.
user_updates bigint
Number of updates by user queries.
last_user_seek datetime
Time of last user seek
last_user_scan datetime
Time of last user scan.
last_user_lookup datetime
Time of last user lookup.
last_user_update datetime
Time of last user update.
system_seeks bigint
Number of seeks by system queries.
system_scans bigint
Number of scans by system queries.
system_lookups bigint
Number of lookups by system queries.
system_updates bigint
Number of updates by system queries.
last_system_seek datetime
Time of last system seek.
last_system_scan datetime
Time of last system scan.
last_system_lookup datetime
Time of last system lookup.
last_system_update datetime
Time of last system update.
Saturday, September 09, 2006
Don't Use Union On Tables With Text Columns
When you have a SQL UNION between 2 or more tables and some of these tables have columns with a text data type use UNION ALL instead of UNION.
If you use UNION you will be given the following message
Server: Msg 8163, Level 16, State 4, Line 10
The text, ntext, or image data type cannot be selected as DISTINCT.
What happens is that UNION use distinct behind the scenes and you can not use distinct on text, ntext or image data types
Run this script to see what I mean
CREATE TABLE TestUnion1 (id INT,textCol TEXT)
CREATE TABLE TestUnion2 (id INT,textCol TEXT)
GO
INSERT TestUnion1 VALUES(1,'abc')
INSERT TestUnion2 VALUES(1,'abc')
INSERT TestUnion1 VALUES(1,'aaa')
INSERT TestUnion1 VALUES(1,'zzz')
INSERT TestUnion1 VALUES(3,'abc')
--problem
SELECT * FROM TestUnion1
UNION --ALL
SELECT * FROM TestUnion2
--no problem
SELECT * FROM TestUnion1
UNION ALL
SELECT * FROM TestUnion2
DROP TABLE TestUnion1,TestUnion2
If you use UNION you will be given the following message
Server: Msg 8163, Level 16, State 4, Line 10
The text, ntext, or image data type cannot be selected as DISTINCT.
What happens is that UNION use distinct behind the scenes and you can not use distinct on text, ntext or image data types
Run this script to see what I mean
CREATE TABLE TestUnion1 (id INT,textCol TEXT)
CREATE TABLE TestUnion2 (id INT,textCol TEXT)
GO
INSERT TestUnion1 VALUES(1,'abc')
INSERT TestUnion2 VALUES(1,'abc')
INSERT TestUnion1 VALUES(1,'aaa')
INSERT TestUnion1 VALUES(1,'zzz')
INSERT TestUnion1 VALUES(3,'abc')
--problem
SELECT * FROM TestUnion1
UNION --ALL
SELECT * FROM TestUnion2
--no problem
SELECT * FROM TestUnion1
UNION ALL
SELECT * FROM TestUnion2
DROP TABLE TestUnion1,TestUnion2
Thursday, September 07, 2006
SQL Server 2005 Failover Clustering White Paper
Microsoft has published a comprehensive document about implementing failover clustering for SQL Server 2005 and Analysis Services
Overview
This white paper is intended for a technical audience and not technical decision makers. It complements the existing documentation around planning, implementing, and administering of a failover cluster that can be found in Microsoft SQL Server 2005 Books Online. To ease the upgrade process for existing users of failover clustering, this white paper also points out differences in the failover clustering implementation of SQL Server 2005 compared to SQL Server 2000.
Get it here
Overview
This white paper is intended for a technical audience and not technical decision makers. It complements the existing documentation around planning, implementing, and administering of a failover cluster that can be found in Microsoft SQL Server 2005 Books Online. To ease the upgrade process for existing users of failover clustering, this white paper also points out differences in the failover clustering implementation of SQL Server 2005 compared to SQL Server 2000.
Get it here
Kalen Delaney Has Finished Inside SQL Server 2005: The Storage Engine And Is Also Blogging On SQLblog.com
Some good news that I am very excited about; Kalen Delaney has finished Inside SQL Server 2005: The Storage Engine. I have already pre-ordered her book but will have to wait until November 8, 2006 when it will ship (hopefully). I have her 2000 edition and it's my favorite book together with Ken Henderson's Guru series. Kalen also has started to blog on SQLblog.com
So what am I currently reading and what else am I going to buy.
Currently I am reading a very good SQL book by Louis Davidson named Pro SQL Server 2005 Database Design and Optimization. I hope to be done by the time Inside SQL Server 2005: The Storage Engine ships, I should be if the kids let me. Pro SQL Server 2005 Database Design and Optimization is a very good book and starts from Data Model and goes all the way to Database Interoperability. some other things covered are Protecting the Integrity of Your Data,Table Structures and Indexing,Coding for Concurrency
This book does also a very good job of explaining Codd’s 12 Rules for an RDBMS
What am I going to buy next?
Next book on my list is Expert SQL Server 2005 Development by Adam Machanic. I like the chapters that Adam wrote in Pro SQL server 2005, I like what he does in newsgroups and I like his blog. So that is enough for me to check out the book
After that I will buy SQL Server 2005 Practical Troubleshooting: The Database Engine by Ken Henderson which will be published December 5, 2006 (Sinterklaas dag for all you Dutch people)
I have 3 of Ken's books and I will get this one and the follow up to The Guru's Guide to SQL Server Stored Procedures, XML, and HTML which will be published May 31, 2007
So I went a little overboard with the links, this post has more blue characters than black ones.
So what is on your list and what are you currently reading?
I am also interested in getting A Developer's Guide to SQL Server 2005 by Bob Beauchemin. We will see; if I finish these books and the others are not published yet then I will. I did not have this problem when I used to take the Amtrak/NJ Transit train from Princeton to New York City (lots of time to read). Right now I work and live in Princeton and my commute is about 8 minutes
So what am I currently reading and what else am I going to buy.
Currently I am reading a very good SQL book by Louis Davidson named Pro SQL Server 2005 Database Design and Optimization. I hope to be done by the time Inside SQL Server 2005: The Storage Engine ships, I should be if the kids let me. Pro SQL Server 2005 Database Design and Optimization is a very good book and starts from Data Model and goes all the way to Database Interoperability. some other things covered are Protecting the Integrity of Your Data,Table Structures and Indexing,Coding for Concurrency
This book does also a very good job of explaining Codd’s 12 Rules for an RDBMS
What am I going to buy next?
Next book on my list is Expert SQL Server 2005 Development by Adam Machanic. I like the chapters that Adam wrote in Pro SQL server 2005, I like what he does in newsgroups and I like his blog. So that is enough for me to check out the book
After that I will buy SQL Server 2005 Practical Troubleshooting: The Database Engine by Ken Henderson which will be published December 5, 2006 (Sinterklaas dag for all you Dutch people)
I have 3 of Ken's books and I will get this one and the follow up to The Guru's Guide to SQL Server Stored Procedures, XML, and HTML which will be published May 31, 2007
So I went a little overboard with the links, this post has more blue characters than black ones.
So what is on your list and what are you currently reading?
I am also interested in getting A Developer's Guide to SQL Server 2005 by Bob Beauchemin. We will see; if I finish these books and the others are not published yet then I will. I did not have this problem when I used to take the Amtrak/NJ Transit train from Princeton to New York City (lots of time to read). Right now I work and live in Princeton and my commute is about 8 minutes
Wednesday, September 06, 2006
Microsoft SQL Server 2005 Everywhere Edition Access Database Synchronizer
Microsoft SQL Server 2005 Everywhere Edition Access Database Synchronizer provides a way to synchronize data between Microsoft Access database on a desktop and Microsoft SQL Server 2005 Everywhere Edition database on a device.
The setup installs the desktop component required for synchronizing Microsoft Access database with SQL Server Everywhere Edition database on the device. It also includes a read me file which has the documentation for the solution and a sample application. The sample application shows how the solution works and how to write applications for this solution. The components installed on the desktop can be used by third party applications to provide data synchronization between Microsoft Access database on the desktop and SQL Server Everywhere/SQL Mobile database on the device.
Download it here
The setup installs the desktop component required for synchronizing Microsoft Access database with SQL Server Everywhere Edition database on the device. It also includes a read me file which has the documentation for the solution and a sample application. The sample application shows how the solution works and how to write applications for this solution. The components installed on the desktop can be used by third party applications to provide data synchronization between Microsoft Access database on the desktop and SQL Server Everywhere/SQL Mobile database on the device.
Download it here
Tuesday, September 05, 2006
Count Those Parentheses
This was a question on the microsoft.public.sqlserver.programming newsgroup, I thought it would be interesting to you to see wat i answered to this one
I believe that I have never used this many parenthese in my life before in a simple 2 column split
This is the question:
I have a column in a table that has multiple pieces of information in it that
I need to break out into various columns. The column is random but the
values I need to separate out are the number and the UN number as below:
245 HELIUM, COMPRESSED 2.2 UN1046
I need to separate the 2.2 and the UN1046 into different columns. How do I
parse this?
Here is the link to the original question at the microsoft.public.sqlserver.programming newsgroup
And here is my solution
CREATE TABLE Inventory (ItemDescription VARCHAR(99))
INSERT Inventory VALUES ('245 HELIUM, COMPRESSED 2.2 UN1046' )
INSERT Inventory VALUES ('24adada5 HELIsadasdadUM, sdsdsd 6.6 UN99' )
INSERT Inventory VALUES ('24adada5 HELIsadasdadUM, sdsdsd 446.6777 UN9988888' )
INSERT Inventory VALUES ('24adada5 HEdUM, sdsdsd 446.0 UN9988' )
SELECT RIGHT(ItemDescription,PATINDEX('% %',
REVERSE(ItemDescription))-1) AS COL1,
LTRIM(REVERSE(LEFT(REVERSE(LEFT(ItemDescription,(LEN(ItemDescription)-PATINDEX('% %', REVERSE(ItemDescription))))),
PATINDEX('% %',REVERSE(LEFT(ItemDescription,(LEN(ItemDescription)-PATINDEX('% %', REVERSE(ItemDescription)))))))))
AS COL2
FROM Inventory
I believe that I have never used this many parenthese in my life before in a simple 2 column split
This is the question:
I have a column in a table that has multiple pieces of information in it that
I need to break out into various columns. The column is random but the
values I need to separate out are the number and the UN number as below:
245 HELIUM, COMPRESSED 2.2 UN1046
I need to separate the 2.2 and the UN1046 into different columns. How do I
parse this?
Here is the link to the original question at the microsoft.public.sqlserver.programming newsgroup
And here is my solution
CREATE TABLE Inventory (ItemDescription VARCHAR(99))
INSERT Inventory VALUES ('245 HELIUM, COMPRESSED 2.2 UN1046' )
INSERT Inventory VALUES ('24adada5 HELIsadasdadUM, sdsdsd 6.6 UN99' )
INSERT Inventory VALUES ('24adada5 HELIsadasdadUM, sdsdsd 446.6777 UN9988888' )
INSERT Inventory VALUES ('24adada5 HEdUM, sdsdsd 446.0 UN9988' )
SELECT RIGHT(ItemDescription,PATINDEX('% %',
REVERSE(ItemDescription))-1) AS COL1,
LTRIM(REVERSE(LEFT(REVERSE(LEFT(ItemDescription,(LEN(ItemDescription)-PATINDEX('% %', REVERSE(ItemDescription))))),
PATINDEX('% %',REVERSE(LEFT(ItemDescription,(LEN(ItemDescription)-PATINDEX('% %', REVERSE(ItemDescription)))))))))
AS COL2
FROM Inventory
SQL Server 2005 And SOA (Service-Oriented Architecture)
A white paper written by Don Kiely about one of the biggest buzzwords of this moment: SOA, Ruby on Rails is the other of course.
Here is an excerpt from the introduction: "The dominant client-server and n-tier application architectures of the 1990s ran into serious scalability and availability issues when used to implement massive Internet e-commerce sites. One of the major problems is that data tended to be stored in a massive, centralized database that all client components had direct access to. Virtually all communication with the database was in the form of SQL statements or batches of statements in a stored procedure, so that the client received a set of data for the specific task at hand.
Other problems arose when trying to incorporate “legacy” systems into newer applications. After decades of deploying a wide variety of systems using various proprietary technologies and platforms, the world was awash in systems that did their job perfectly well but had no clear path to interact with other applications in an increasingly connected environment. Achieving the agility needed by today’s applications has been extremely difficult. Business-to-business (B2B) interactions complicate things even further, requiring standard and reliable ways of conducting business electronically. Clearly, evolving systems that meet the needs of today’s global"
Read the complete white paper here: How SQL Server 2005 Enables Service-Oriented Database Architectures
Here is an excerpt from the introduction: "The dominant client-server and n-tier application architectures of the 1990s ran into serious scalability and availability issues when used to implement massive Internet e-commerce sites. One of the major problems is that data tended to be stored in a massive, centralized database that all client components had direct access to. Virtually all communication with the database was in the form of SQL statements or batches of statements in a stored procedure, so that the client received a set of data for the specific task at hand.
Other problems arose when trying to incorporate “legacy” systems into newer applications. After decades of deploying a wide variety of systems using various proprietary technologies and platforms, the world was awash in systems that did their job perfectly well but had no clear path to interact with other applications in an increasingly connected environment. Achieving the agility needed by today’s applications has been extremely difficult. Business-to-business (B2B) interactions complicate things even further, requiring standard and reliable ways of conducting business electronically. Clearly, evolving systems that meet the needs of today’s global"
Read the complete white paper here: How SQL Server 2005 Enables Service-Oriented Database Architectures
Friday, September 01, 2006
SQL Server 2005 Best Practices Analyzer Coming Soon??
Microsoft Events has the following TechNet Webcast: Using the SQL Server Upgrade Advisor and New SQL Server 2005 Best Practices Analyzer Tools (Level 200)
Start Time: Thursday, September 07, 2006 9:30 AM Pacific Time (US & Canada)
End Time: Thursday, September 07, 2006 11:00 AM Pacific Time (US & Canada)
Description: Do you have plans to upgrade to Microsoft SQL Server 2005 in the near future? In this presentation, we describe two valuable tools from Microsoft that can help you identify and address potential issues proactively for a smoother upgrade experience. The Microsoft SQL Server 2005 Upgrade Advisor analyzes existing instances of Microsoft SQL Server 7.0 and SQL Server 2000, identifies feature and configuration changes that might affect your upgrade, and provides links to documentation that describes each issue and how to resolve it. The new SQL Server 2005 Best Practices Analyzer tool helps you ensure that SQL Server instances, databases, and SQL Server Integration Services (SSIS) packages adhere to Microsoft best practices. Attend this webcast to learn how to use these tools and how they can help you upgrade your SQL Server environment effectively and efficiently.
Presenter: Paul Mestemaker, Program Manager, Microsoft Corporation
So does this mean that the SQL Server 2005 Best Practices Analyzer is near completion? I don't know but I did ask the same question on the SQL Server Relational Engine Manageability Team Blog
And to give credit where credit is due I saw this first on Dis4ea's SQL Blog
Start Time: Thursday, September 07, 2006 9:30 AM Pacific Time (US & Canada)
End Time: Thursday, September 07, 2006 11:00 AM Pacific Time (US & Canada)
Description: Do you have plans to upgrade to Microsoft SQL Server 2005 in the near future? In this presentation, we describe two valuable tools from Microsoft that can help you identify and address potential issues proactively for a smoother upgrade experience. The Microsoft SQL Server 2005 Upgrade Advisor analyzes existing instances of Microsoft SQL Server 7.0 and SQL Server 2000, identifies feature and configuration changes that might affect your upgrade, and provides links to documentation that describes each issue and how to resolve it. The new SQL Server 2005 Best Practices Analyzer tool helps you ensure that SQL Server instances, databases, and SQL Server Integration Services (SSIS) packages adhere to Microsoft best practices. Attend this webcast to learn how to use these tools and how they can help you upgrade your SQL Server environment effectively and efficiently.
Presenter: Paul Mestemaker, Program Manager, Microsoft Corporation
So does this mean that the SQL Server 2005 Best Practices Analyzer is near completion? I don't know but I did ask the same question on the SQL Server Relational Engine Manageability Team Blog
And to give credit where credit is due I saw this first on Dis4ea's SQL Blog
Top SQL Server Google Searches For August 2006
These are the top SQL Searches on this site for the month of August I have left out searches that have nothing to do with SQL Server or programming (for example atlantic city escorts)
Here are the results...
dtsrun from sp
query multiple databases
first business day of each month query
Truncated table recovery
check constraint
dbcc report files
first business day of each month
String or binary data would be truncated.
SQL SELECT *
substr()
Login failed for user '(null)'. Reason: Not associated with a trusted SQL Server connection.
xp_fileexist
SQL SELECT WHERE DATE
CONCAT_NULL_YIELDS_NULL
check constrant
SQL 2000 parallel backup restore
dtsrun
Let's talk about a couple of these
query multiple databases
I covered that in this post
first business day of each month query
You really need to have a calendar table for this one. You can also use a number table and check for the min date where select datepart(dw,date) between 2 and 6 but what about holidays. A calendar table is your best bet. And I know just a place to get some code for that-->A way to load a calendar table
Login failed for user '(null)'. Reason: Not associated with a trusted SQL Server connection.
That can be found here: 2000 version, 2005 version
xp_fileexist
That is covered here
String or binary data would be truncated
And that was covered here
So there you have it, those were some of the searches and I covered some of that stuff already. I always like to look at the searches because it gives me ideas for future blog posts
Here are the results...
dtsrun from sp
query multiple databases
first business day of each month query
Truncated table recovery
check constraint
dbcc report files
first business day of each month
String or binary data would be truncated.
SQL SELECT *
substr()
Login failed for user '(null)'. Reason: Not associated with a trusted SQL Server connection.
xp_fileexist
SQL SELECT WHERE DATE
CONCAT_NULL_YIELDS_NULL
check constrant
SQL 2000 parallel backup restore
dtsrun
Let's talk about a couple of these
query multiple databases
I covered that in this post
first business day of each month query
You really need to have a calendar table for this one. You can also use a number table and check for the min date where select datepart(dw,date) between 2 and 6 but what about holidays. A calendar table is your best bet. And I know just a place to get some code for that-->A way to load a calendar table
Login failed for user '(null)'. Reason: Not associated with a trusted SQL Server connection.
That can be found here: 2000 version, 2005 version
xp_fileexist
That is covered here
String or binary data would be truncated
And that was covered here
So there you have it, those were some of the searches and I covered some of that stuff already. I always like to look at the searches because it gives me ideas for future blog posts
Top 5 Posts For The Month Of August
Below are the top 5 posts according to Google Analytics for the month of August
Here are the posts in order by pageviews descending
Store The Output Of A Stored Procedure In A Table Without Creating A Table
6 Different Ways To Get The Current Identity Value From A Table
COALESCE And ISNULL Differences
Login failed for user 'sa'. Reason: Not associated with a trusted SQL Server connection. SQL 2005
OPENROWSET And Excel Problems
And I have also updated the Top 10 Articles of all time
Here are the posts in order by pageviews descending
Store The Output Of A Stored Procedure In A Table Without Creating A Table
6 Different Ways To Get The Current Identity Value From A Table
COALESCE And ISNULL Differences
Login failed for user 'sa'. Reason: Not associated with a trusted SQL Server connection. SQL 2005
OPENROWSET And Excel Problems
And I have also updated the Top 10 Articles of all time
Thursday, August 31, 2006
sys.dm_exec_sessions
As I promised earlier today, here is the first of many posts about the Dynamic Management Views in SQL Server 2005.
What does the sys.dm_exec_sessions view return? It looks like it is a combination of DBCC USEROPTION and sp_who. Let's for example find out how many sessions are running, sleeping or dormant
Just a quick count of all the sessions
SELECT COUNT(*) as StatusCount,CASE status
WHEN 'Running' THEN 'Running - Currently running one or more requests'
WHEN 'Sleeping ' THEN 'Sleeping - Currently running no requests'
ELSE 'Dormant – Session is in prelogin state' END status
FROM sys.dm_exec_sessions
GROUP BY status
Let's list all SPID's
SELECT session_id,CASE status
WHEN 'Running' THEN 'Running - Currently running one or more requests'
WHEN 'Sleeping ' THEN 'Sleeping - Currently running no requests'
ELSE 'Dormant – Session is in prelogin state' END status
FROM sys.dm_exec_sessions
Let's just grab our own SPID
SELECT session_id,CASE status
WHEN 'Running' THEN 'Running - Currently running one or more requests'
WHEN 'Sleeping ' THEN 'Sleeping - Currently running no requests'
ELSE 'Dormant – Session is in prelogin state' END status
FROM sys.dm_exec_sessions
WHERE session_id = @@SPID
Now let's query all user sessions
SELECT * FROM sys.dm_exec_sessions
WHERE is_user_process =0
Then for the server you would change 0 to 1
SELECT * FROM sys.dm_exec_sessions
WHERE is_user_process =1
Just a quick count of all the transaction isolation levels
SELECT COUNT(*),CASE transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'ReadUncomitted'
WHEN 2 THEN 'Readcomitted'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL
FROM sys.dm_exec_sessions
GROUP BY transaction_isolation_level
Let's look at some of these ANSI settings and while we are at it let's use UNPIVOT to return the results vertically
SELECT SPID,Value,ANSI_SETTING
FROM (
SELECT @@SPID as SPID,
CASE quoted_identifier
WHEN 1 THEN 'SET' ELSE 'OFF' END QUOTED_IDENTIFIER,
CASE arithabort
WHEN 1 THEN 'SET' ELSE 'OFF' END ARITHABORT,
CASE ansi_null_dflt_on
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULL_DFLT_ON,
CASE ansi_defaults
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_DEFAULTS ,
CASE ansi_warnings
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_WARNINGS,
CASE ansi_padding
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_PADDING,
CASE ansi_nulls
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULLS,
CASE concat_null_yields_null
WHEN 1 THEN 'SET' ELSE 'OFF' END CONCAT_NULL_YIELDS_NULL
FROM sys.dm_exec_sessions
WHERE session_id = @@SPID ) P
UNPIVOT (Value for ANSI_SETTING IN(
QUOTED_IDENTIFIER,ARITHABORT,ANSI_NULL_DFLT_ON,
ANSI_DEFAULTS,ANSI_WARNINGS,
ANSI_PADDING,ANSI_NULLS,CONCAT_NULL_YIELDS_NULL
)
) AS unpvt
Now let's see if we can duplicate DBCC USEROPTIONS
First run DBCC USEROPTIONS
And then run the following:
SELECT @@SPID as SPID,
CASE quoted_identifier
WHEN 1 THEN 'SET' ELSE 'OFF' END QUOTED_IDENTIFIER,
CASE arithabort
WHEN 1 THEN 'SET' ELSE 'OFF' END ARITHABORT,
CASE ansi_null_dflt_on
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULL_DFLT_ON,
CASE ansi_defaults
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_DEFAULTS ,
CASE ansi_warnings
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_WARNINGS,
CASE ansi_padding
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_PADDING,
CASE ansi_nulls
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULLS,
CASE concat_null_yields_null
WHEN 1 THEN 'SET' ELSE 'OFF' END CONCAT_NULL_YIELDS_NULL,
CASE transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'ReadUncomitted'
WHEN 2 THEN 'Readcomitted'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL,lock_timeout,date_first,date_format
FROM sys.dm_exec_sessions
WHERE session_id = @@SPID
It's probably not exactly the same and I don't know if I missed a column but below is the whole definition of the view and you can experiment with this yourself
Below is what the sys.dm_exec_sessions view returns
On the first line are the column name and the data type, below that is the description
sys.dm_exec_sessions
session_id smallint
Identifies the session associated with each active primary connection.
login_time datetime
Time when session was established.
host_name nvarchar(128)
Host associated with the session.
program_name nvarchar(128)
Program associated with the session.
host_process_id int
Process ID associated with the session.
client_version int
Version of the interface used by the client to connect to the Server.
client_interface_name nvarchar(32)
Name of the interface used by the client to connect to the Server.
security_id varbinary(85)
Microsoft Windows security ID associated with the login.
login_name nvarchar(128)
SQL Login Name associated with the session.
nt_domain nvarchar(128)
Domain from which session connection was made.
nt_user_name nvarchar(128)
Name of the user associated with the session.
status nvarchar(30)
Status of the session. Possible values:
-- Running - Currently running one or more requests
-- Sleeping - Currently running no requests
-- Dormant – Session is in prelogin state
context_info varbinary(128)
CONTEXT_INFO value for the session.
cpu_time int
CPU time, in milliseconds, that was used by this session.
memory_usage int
Number of 8-KB pages of memory used by this session.
total_scheduled_time int
Total time, in milliseconds, for which the session (requests within) were scheduled for execution.
total_elapsed_time int
Time, in milliseconds, since the session was established.
endpoint_id int
ID of the Endpoint associated with the session.
last_request_start_time datetime
Time at which the last request on the session began. This includes the currently executing request.
last_request_end_time datetime
Time of the last completion of a request on the session.
reads bigint
Number of reads performed, by requests in this session, during this session.
writes bigint
Number of writes performed, by requests in this session, during this session.
logical_reads bigint
Number of logical reads that have been performed on the session.
is_user_process bit
0 if the session is a system session. Otherwise, it is 1.
text_size int
TEXTSIZE setting for the session.
language nvarchar(128)
LANGUAGE setting for the session.
date_format nvarchar(3)
DATEFORMAT setting for the session.
date_first smallint
DATEFIRST setting for the session.
quoted_identifier bit
QUOTED_IDENTIFIER setting for the session.
arithabort bit
ARITHABORT setting for the session.
ansi_null_dflt_on bit
ANSI_NULL_DFLT_ON setting for the session.
ansi_defaults bit
ANSI_DEFAULTS setting for the session.
ansi_warnings bit
ANSI_WARNINGS setting for the session.
ansi_padding bit
ANSI_PADDING setting for the session.
ansi_nulls bit
ANSI_NULLS setting for the session.
concat_null_yields_null bit
CONCAT_NULL_YIELDS_NULL setting for the session.
transaction_isolation_level smallint
Transaction isolation level of the session.
-- 0 = Unspecified
-- 1 = ReadUncomitted
-- 2 = ReadCommitted
-- 3 = Repeatable
-- 4 = Serializable
-- 5 = Snapshot
lock_timeout int
LOCK_TIMEOUT setting for the session. The value is in milliseconds.
deadlock_priority int
DEADLOCK_PRIORITY setting for the session.
row_count bigint
number of rows returned on the session up to this point.
prev_error int
ID of the last error returned on the session.
So that's it for today, the view contains a lot more than I covered. i might expand this if I have time. If you have any suggestions leave me a comment or drop me an Email
The link to the post with all the views is here (as of today this is the only view that is covered)
What does the sys.dm_exec_sessions view return? It looks like it is a combination of DBCC USEROPTION and sp_who. Let's for example find out how many sessions are running, sleeping or dormant
Just a quick count of all the sessions
SELECT COUNT(*) as StatusCount,CASE status
WHEN 'Running' THEN 'Running - Currently running one or more requests'
WHEN 'Sleeping ' THEN 'Sleeping - Currently running no requests'
ELSE 'Dormant – Session is in prelogin state' END status
FROM sys.dm_exec_sessions
GROUP BY status
Let's list all SPID's
SELECT session_id,CASE status
WHEN 'Running' THEN 'Running - Currently running one or more requests'
WHEN 'Sleeping ' THEN 'Sleeping - Currently running no requests'
ELSE 'Dormant – Session is in prelogin state' END status
FROM sys.dm_exec_sessions
Let's just grab our own SPID
SELECT session_id,CASE status
WHEN 'Running' THEN 'Running - Currently running one or more requests'
WHEN 'Sleeping ' THEN 'Sleeping - Currently running no requests'
ELSE 'Dormant – Session is in prelogin state' END status
FROM sys.dm_exec_sessions
WHERE session_id = @@SPID
Now let's query all user sessions
SELECT * FROM sys.dm_exec_sessions
WHERE is_user_process =0
Then for the server you would change 0 to 1
SELECT * FROM sys.dm_exec_sessions
WHERE is_user_process =1
Just a quick count of all the transaction isolation levels
SELECT COUNT(*),CASE transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'ReadUncomitted'
WHEN 2 THEN 'Readcomitted'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL
FROM sys.dm_exec_sessions
GROUP BY transaction_isolation_level
Let's look at some of these ANSI settings and while we are at it let's use UNPIVOT to return the results vertically
SELECT SPID,Value,ANSI_SETTING
FROM (
SELECT @@SPID as SPID,
CASE quoted_identifier
WHEN 1 THEN 'SET' ELSE 'OFF' END QUOTED_IDENTIFIER,
CASE arithabort
WHEN 1 THEN 'SET' ELSE 'OFF' END ARITHABORT,
CASE ansi_null_dflt_on
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULL_DFLT_ON,
CASE ansi_defaults
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_DEFAULTS ,
CASE ansi_warnings
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_WARNINGS,
CASE ansi_padding
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_PADDING,
CASE ansi_nulls
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULLS,
CASE concat_null_yields_null
WHEN 1 THEN 'SET' ELSE 'OFF' END CONCAT_NULL_YIELDS_NULL
FROM sys.dm_exec_sessions
WHERE session_id = @@SPID ) P
UNPIVOT (Value for ANSI_SETTING IN(
QUOTED_IDENTIFIER,ARITHABORT,ANSI_NULL_DFLT_ON,
ANSI_DEFAULTS,ANSI_WARNINGS,
ANSI_PADDING,ANSI_NULLS,CONCAT_NULL_YIELDS_NULL
)
) AS unpvt
Now let's see if we can duplicate DBCC USEROPTIONS
First run DBCC USEROPTIONS
And then run the following:
SELECT @@SPID as SPID,
CASE quoted_identifier
WHEN 1 THEN 'SET' ELSE 'OFF' END QUOTED_IDENTIFIER,
CASE arithabort
WHEN 1 THEN 'SET' ELSE 'OFF' END ARITHABORT,
CASE ansi_null_dflt_on
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULL_DFLT_ON,
CASE ansi_defaults
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_DEFAULTS ,
CASE ansi_warnings
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_WARNINGS,
CASE ansi_padding
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_PADDING,
CASE ansi_nulls
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULLS,
CASE concat_null_yields_null
WHEN 1 THEN 'SET' ELSE 'OFF' END CONCAT_NULL_YIELDS_NULL,
CASE transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'ReadUncomitted'
WHEN 2 THEN 'Readcomitted'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL,lock_timeout,date_first,date_format
FROM sys.dm_exec_sessions
WHERE session_id = @@SPID
It's probably not exactly the same and I don't know if I missed a column but below is the whole definition of the view and you can experiment with this yourself
Below is what the sys.dm_exec_sessions view returns
On the first line are the column name and the data type, below that is the description
sys.dm_exec_sessions
session_id smallint
Identifies the session associated with each active primary connection.
login_time datetime
Time when session was established.
host_name nvarchar(128)
Host associated with the session.
program_name nvarchar(128)
Program associated with the session.
host_process_id int
Process ID associated with the session.
client_version int
Version of the interface used by the client to connect to the Server.
client_interface_name nvarchar(32)
Name of the interface used by the client to connect to the Server.
security_id varbinary(85)
Microsoft Windows security ID associated with the login.
login_name nvarchar(128)
SQL Login Name associated with the session.
nt_domain nvarchar(128)
Domain from which session connection was made.
nt_user_name nvarchar(128)
Name of the user associated with the session.
status nvarchar(30)
Status of the session. Possible values:
-- Running - Currently running one or more requests
-- Sleeping - Currently running no requests
-- Dormant – Session is in prelogin state
context_info varbinary(128)
CONTEXT_INFO value for the session.
cpu_time int
CPU time, in milliseconds, that was used by this session.
memory_usage int
Number of 8-KB pages of memory used by this session.
total_scheduled_time int
Total time, in milliseconds, for which the session (requests within) were scheduled for execution.
total_elapsed_time int
Time, in milliseconds, since the session was established.
endpoint_id int
ID of the Endpoint associated with the session.
last_request_start_time datetime
Time at which the last request on the session began. This includes the currently executing request.
last_request_end_time datetime
Time of the last completion of a request on the session.
reads bigint
Number of reads performed, by requests in this session, during this session.
writes bigint
Number of writes performed, by requests in this session, during this session.
logical_reads bigint
Number of logical reads that have been performed on the session.
is_user_process bit
0 if the session is a system session. Otherwise, it is 1.
text_size int
TEXTSIZE setting for the session.
language nvarchar(128)
LANGUAGE setting for the session.
date_format nvarchar(3)
DATEFORMAT setting for the session.
date_first smallint
DATEFIRST setting for the session.
quoted_identifier bit
QUOTED_IDENTIFIER setting for the session.
arithabort bit
ARITHABORT setting for the session.
ansi_null_dflt_on bit
ANSI_NULL_DFLT_ON setting for the session.
ansi_defaults bit
ANSI_DEFAULTS setting for the session.
ansi_warnings bit
ANSI_WARNINGS setting for the session.
ansi_padding bit
ANSI_PADDING setting for the session.
ansi_nulls bit
ANSI_NULLS setting for the session.
concat_null_yields_null bit
CONCAT_NULL_YIELDS_NULL setting for the session.
transaction_isolation_level smallint
Transaction isolation level of the session.
-- 0 = Unspecified
-- 1 = ReadUncomitted
-- 2 = ReadCommitted
-- 3 = Repeatable
-- 4 = Serializable
-- 5 = Snapshot
lock_timeout int
LOCK_TIMEOUT setting for the session. The value is in milliseconds.
deadlock_priority int
DEADLOCK_PRIORITY setting for the session.
row_count bigint
number of rows returned on the session up to this point.
prev_error int
ID of the last error returned on the session.
So that's it for today, the view contains a lot more than I covered. i might expand this if I have time. If you have any suggestions leave me a comment or drop me an Email
The link to the post with all the views is here (as of today this is the only view that is covered)
Dynamic Management Views Blog Post Series Coming To A Screen Near You
Dynamic Management Views Blog Post Series Coming To A Screen Near You
Since I don't always know what to write I decided to give myself enough material for at least 6 months (if I cover 1 view a week). So here it is I will write about the Dynamic Management Views in SQL server 2005. The first view that I will cover is sys.dm_exec_sessions. You can use sys.dm_exec_sessions instead of DBCC USEROPTIONS only it's much better since you can query multiple SPID's
I will have the first post ready about 4:30 PM EST today
Here is a list of all the Dynamic Management Views in SQL Server 2005, I will link the ones that I write about to the post so that you can access all of this from 1 post (in theory)
Common Language Runtime Related Dynamic Management Views
sys.dm_clr_appdomains
sys.dm_clr_loaded_assemblies
sys.dm_clr_properties
sys.dm_clr_tasks
Database Mirroring Related Dynamic Management Views
sys.dm_db_mirroring_connections
Database Related Dynamic Management Views
sys.dm_db_file_space_usage
sys.dm_db_session_space_usage
sys.dm_db_partition_stats
sys.dm_db_task_space_usage
Execution Related Dynamic Management Views and Functions
sys.dm_exec_background_job_queue
sys.dm_exec_background_job_queue_stats
sys.dm_exec_cached_plans
sys.dm_exec_connections
sys.dm_exec_cursors
sys.dm_exec_plan_attributes
sys.dm_exec_query_optimizer_info
sys.dm_exec_query_plan
sys.dm_exec_query_stats
sys.dm_exec_requests
sys.dm_exec_sessions added on 2006-08-31
sys.dm_exec_sql_text
Full-Text Search Related Dynamic Management Views
sys.dm_fts_active_catalogs
sys.dm_fts_crawls
sys.dm_fts_crawl_ranges
sys.dm_fts_memory_buffers
sys.dm_fts_memory_pools
Index Related Dynamic Management Views and Functions
sys.dm_db_index_operational_stats
sys.dm_db_index_physical_stats
sys.dm_db_index_usage_stats added on 2006-09-10
I/O Related Dynamic Management Views and Functions
sys.dm_io_backup_tapes
sys.dm_io_cluster_shared_drives
sys.dm_io_pending_io_requests
sys.dm_io_virtual_file_stats
Query Notifications Related Dynamic Management Views
sys.dm_qn_subscriptions
Replication Related Dynamic Management Views
sys.dm_repl_articles
sys.dm_repl_schemas
sys.dm_repl_tranhash
sys.dm_repl_traninfo
Service Broker Related Dynamic Management Views
sys.dm_broker_activated_tasks
sys.dm_broker_connections
sys.dm_broker_forwarded_messages
sys.dm_broker_queue_monitors
SQL Operating System Related Dynamic Management Views
sys.dm_os_buffer_descriptors
sys.dm_os_memory_pools
sys.dm_os_child_instances
sys.dm_os_performance_counters
sys.dm_os_cluster_nodes
sys.dm_os_schedulers
sys.dm_os_hosts
sys.dm_os_stacks
sys.dm_os_latch_stats
sys.dm_os_sys_info
sys.dm_os_loaded_modules
sys.dm_os_tasks
sys.dm_os_memory_cache_clock_hands
sys.dm_os_threads
sys.dm_os_memory_cache_counters
sys.dm_os_virtual_address_dump
sys.dm_os_memory_cache_entries
sys.dm_os_wait_stats
sys.dm_os_memory_cache_hash_tables
sys.dm_os_waiting_tasks
sys.dm_os_memory_clerks
sys.dm_os_workers
sys.dm_os_memory_objects
Transaction Related Dynamic Management Views and Functions
sys.dm_tran_active_snapshot_database_transactions
sys.dm_tran_active_transactions
sys.dm_tran_current_snapshot
sys.dm_tran_current_transaction
sys.dm_tran_database_transactions
sys.dm_tran_locks
sys.dm_tran_session_transactions
sys.dm_tran_top_version_generators
sys.dm_tran_transactions_snapshot
sys.dm_tran_version_store
Since I don't always know what to write I decided to give myself enough material for at least 6 months (if I cover 1 view a week). So here it is I will write about the Dynamic Management Views in SQL server 2005. The first view that I will cover is sys.dm_exec_sessions. You can use sys.dm_exec_sessions instead of DBCC USEROPTIONS only it's much better since you can query multiple SPID's
I will have the first post ready about 4:30 PM EST today
Here is a list of all the Dynamic Management Views in SQL Server 2005, I will link the ones that I write about to the post so that you can access all of this from 1 post (in theory)
Common Language Runtime Related Dynamic Management Views
sys.dm_clr_appdomains
sys.dm_clr_loaded_assemblies
sys.dm_clr_properties
sys.dm_clr_tasks
Database Mirroring Related Dynamic Management Views
sys.dm_db_mirroring_connections
Database Related Dynamic Management Views
sys.dm_db_file_space_usage
sys.dm_db_session_space_usage
sys.dm_db_partition_stats
sys.dm_db_task_space_usage
Execution Related Dynamic Management Views and Functions
sys.dm_exec_background_job_queue
sys.dm_exec_background_job_queue_stats
sys.dm_exec_cached_plans
sys.dm_exec_connections
sys.dm_exec_cursors
sys.dm_exec_plan_attributes
sys.dm_exec_query_optimizer_info
sys.dm_exec_query_plan
sys.dm_exec_query_stats
sys.dm_exec_requests
sys.dm_exec_sessions added on 2006-08-31
sys.dm_exec_sql_text
Full-Text Search Related Dynamic Management Views
sys.dm_fts_active_catalogs
sys.dm_fts_crawls
sys.dm_fts_crawl_ranges
sys.dm_fts_memory_buffers
sys.dm_fts_memory_pools
Index Related Dynamic Management Views and Functions
sys.dm_db_index_operational_stats
sys.dm_db_index_physical_stats
sys.dm_db_index_usage_stats added on 2006-09-10
I/O Related Dynamic Management Views and Functions
sys.dm_io_backup_tapes
sys.dm_io_cluster_shared_drives
sys.dm_io_pending_io_requests
sys.dm_io_virtual_file_stats
Query Notifications Related Dynamic Management Views
sys.dm_qn_subscriptions
Replication Related Dynamic Management Views
sys.dm_repl_articles
sys.dm_repl_schemas
sys.dm_repl_tranhash
sys.dm_repl_traninfo
Service Broker Related Dynamic Management Views
sys.dm_broker_activated_tasks
sys.dm_broker_connections
sys.dm_broker_forwarded_messages
sys.dm_broker_queue_monitors
SQL Operating System Related Dynamic Management Views
sys.dm_os_buffer_descriptors
sys.dm_os_memory_pools
sys.dm_os_child_instances
sys.dm_os_performance_counters
sys.dm_os_cluster_nodes
sys.dm_os_schedulers
sys.dm_os_hosts
sys.dm_os_stacks
sys.dm_os_latch_stats
sys.dm_os_sys_info
sys.dm_os_loaded_modules
sys.dm_os_tasks
sys.dm_os_memory_cache_clock_hands
sys.dm_os_threads
sys.dm_os_memory_cache_counters
sys.dm_os_virtual_address_dump
sys.dm_os_memory_cache_entries
sys.dm_os_wait_stats
sys.dm_os_memory_cache_hash_tables
sys.dm_os_waiting_tasks
sys.dm_os_memory_clerks
sys.dm_os_workers
sys.dm_os_memory_objects
Transaction Related Dynamic Management Views and Functions
sys.dm_tran_active_snapshot_database_transactions
sys.dm_tran_active_transactions
sys.dm_tran_current_snapshot
sys.dm_tran_current_transaction
sys.dm_tran_database_transactions
sys.dm_tran_locks
sys.dm_tran_session_transactions
sys.dm_tran_top_version_generators
sys.dm_tran_transactions_snapshot
sys.dm_tran_version_store
Wednesday, August 30, 2006
A SQL Super Hero Is Born
Ken Henderson promised to give away a signed book to the person who made the best Celko superhero
Tom Øyvind Hogstad has created one on his blog and I think it looks pretty good, even the S in the logo can stay; we can assume it stands for SQL
Below you will find my favorite Celko answer ever
>> how to set the PK in SS Mgmt Studio ? <<
Who cares?? You are not not a real SQL programmer!! You are a "mousey, mousey, click , click" non-programmer. (with a French accent) we spit on you, Video gamer! to be serious, real programmers use a text editor. They know the language they write in. Those stinking "video game tools"slow us down. And they lead us to ask questiosn like this in newsgroups where people liek me will maek fun of you.
You can find more of these Celko ‘answers on Joe Celko The SQL Apprentice
Tom Øyvind Hogstad has created one on his blog and I think it looks pretty good, even the S in the logo can stay; we can assume it stands for SQL
Below you will find my favorite Celko answer ever
>> how to set the PK in SS Mgmt Studio ? <<
Who cares?? You are not not a real SQL programmer!! You are a "mousey, mousey, click , click" non-programmer. (with a French accent) we spit on you, Video gamer! to be serious, real programmers use a text editor. They know the language they write in. Those stinking "video game tools"slow us down. And they lead us to ask questiosn like this in newsgroups where people liek me will maek fun of you.
You can find more of these Celko ‘answers on Joe Celko The SQL Apprentice
Tuesday, August 29, 2006
Visual Studio 2005 Team Edition For Database Professionals Review On Regdeveloper
The Register has a review on their subsite Regdeveloper about Visual Studio 2005 Team Edition For Database Professionals (also know as Data Dude) There are 3 pictures so that you can see what the tool looks like if you are afraid to install the latest Community Technology Preview on your system( you can get the latest release here )
The review is very positive about the tool and this will be one of those tools that you have to have in your shop, just as is the case with SQL Compare and SQL LiteSpeed right now.
There is one little problem with the review in the following sentence: "DD was partially the brainchild of Ewan Garden and Gert Drapers" they managed to spell Euan Garden's name wrong
Read the review here
The review is very positive about the tool and this will be one of those tools that you have to have in your shop, just as is the case with SQL Compare and SQL LiteSpeed right now.
There is one little problem with the review in the following sentence: "DD was partially the brainchild of Ewan Garden and Gert Drapers" they managed to spell Euan Garden's name wrong
Read the review here
Monday, August 28, 2006
Round Up Or Down To Nearest Percentage Value By Using FLOOR And CEILING
Let's say you have a value of 13.33 and you want to round this up and down to the nearest .25 in other words for 13.33 you want to display 13.25 and 13.50.How do you do that? It's pretty easy you do FLOOR(Value *4)/4 and CEILING(Value *4)/4
Below are 3 example, 1 for 0.25, 1 for 0.50 and 1 for 0.33
--0.25
DECLARE @Value DECIMAL(10,2)
SET @Value = 13.33
SELECT FLOOR(@Value * 4) / 4.0,CEILING(@Value * 4) / 4.0
GO
--0.50
DECLARE @Value DECIMAL(10,2)
SET @Value = 13.33
SELECT FLOOR(@Value * 2) / 2.0,CEILING(@Value * 2) / 2.0
GO
--0.33
DECLARE @Value DECIMAL(10,2)
SET @Value = 13.36
SELECT FLOOR(@Value * 3) / 3.0,CEILING(@Value * 3) / 3.
Below are 3 example, 1 for 0.25, 1 for 0.50 and 1 for 0.33
--0.25
DECLARE @Value DECIMAL(10,2)
SET @Value = 13.33
SELECT FLOOR(@Value * 4) / 4.0,CEILING(@Value * 4) / 4.0
GO
--0.50
DECLARE @Value DECIMAL(10,2)
SET @Value = 13.33
SELECT FLOOR(@Value * 2) / 2.0,CEILING(@Value * 2) / 2.0
GO
--0.33
DECLARE @Value DECIMAL(10,2)
SET @Value = 13.36
SELECT FLOOR(@Value * 3) / 3.0,CEILING(@Value * 3) / 3.
Friday, August 25, 2006
Win One Of Ken Henderson's SQL Server Guru Books By Creating A PhotoShop Joe Celko Action Figure
That's right you can win one of the following three books
The Guru's Guide to Transact-SQL
The Guru's Guide to SQL Server Architecture and Internals
The Guru's Guide to SQL Server Stored Procedures, XML, and HTML
All you have to do is create a photoshopped depiction of Joe Celko as an action figure.
The best one gets a signed copy of one of his books (too bad I already have all three)
Ken Henderson's Blog
The Guru's Guide to Transact-SQL
The Guru's Guide to SQL Server Architecture and Internals
The Guru's Guide to SQL Server Stored Procedures, XML, and HTML
All you have to do is create a photoshopped depiction of Joe Celko as an action figure.
The best one gets a signed copy of one of his books (too bad I already have all three)
Ken Henderson's Blog
Friday Joke and Frappr Map Update
Since it's Friday today I will keep it light
Let's start with a joke that I read in Wired magazine yesterday
What do you call a blonde who dyes her hair brown?
Artificial intelligence
Next topic
Yesterday I created a Frappr map and asked for you (the reader) to add yourself to the map so that I can see where some of you are located
As of now the countries that are marked are
United States 6 people
Russia 2 people
Canada 1 person
Norway 1 person
So not quite close to my IQ yet
Let's start with a joke that I read in Wired magazine yesterday
What do you call a blonde who dyes her hair brown?
Artificial intelligence
Next topic
Yesterday I created a Frappr map and asked for you (the reader) to add yourself to the map so that I can see where some of you are located
As of now the countries that are marked are
United States 6 people
Russia 2 people
Canada 1 person
Norway 1 person
So not quite close to my IQ yet
Thursday, August 24, 2006
SqlServerCode Frappr Map
I created a Frappr Map and would like for you (yes you the reader) to add yourself to the map because it would be interesting to see where some of the readers of this blog are located
So far I have less members (2) than my IQ, I would like to have more members than my IQ (believe me not a hard task at all)
So this is your chance; beat my IQ
My member name is Denis The SQL Menace
So far I have less members (2) than my IQ, I would like to have more members than my IQ (believe me not a hard task at all)
So this is your chance; beat my IQ
My member name is Denis The SQL Menace
Quest Toad for SQL Server 2.0 Released
Quest Software, Inc. announced the newest version of its award-winning Toad™ database management product family. Toad for SQL Server 2.0 includes new features such as one-of-a-kind integrated debugging, SQL optimization, and integrated comparison and synchronization capabilities for SQL Server 2005. These new features further improve the productivity of SQL Server developers and database administrators (DBAs).
New features in version 2.0 of Toad for SQL Server include:
Pricing and Availability
A freeware version of 2.0 of Quest Toad for SQL Server is available now at http://www.toadsoft.com/toadsqlserver/toad_sqlserver.htm
A full production version is also available now with North American pricing beginning at $470 per seat (USD). For more information and to download free evaluation copies please visit: http://www.quest.com/toad_for_sql_server/
New features in version 2.0 of Toad for SQL Server include:
- Database Back-Up Indicator – Demonstrates when it is necessary to back up a system, and integrates seamlessly with LiteSpeed for SQL Server
- SQL Optimization - Automates the process of identifying problematic SQL then re-writing and benchmarking it for optimal SQL Server performance.
- Compare and Sync – Provides advanced integrated comparison and synchronization of schema, data and server settings of two SQL Server environments.
- Debugging – Offers integrated debugging capabilities for SQL Server 2005.
Pricing and Availability
A freeware version of 2.0 of Quest Toad for SQL Server is available now at http://www.toadsoft.com/toadsqlserver/toad_sqlserver.htm
A full production version is also available now with North American pricing beginning at $470 per seat (USD). For more information and to download free evaluation copies please visit: http://www.quest.com/toad_for_sql_server/
Tuesday, August 22, 2006
DDL Trigger Events Revisited
Many many moons ago I wrote about DDL Trigger Events
I promised that I would find out all the events that you can combine for example DDL_VIEW_EVENTS instead of CREATE_VIEW
,ALTER_VIEW and DROP_VIEW
So I finally did it, I created a bunch of triggers and then checked with a query that joined sys.triggers and sys.trigger_events
I started by creating a trigger and I used DDL_VIEW_EVENTS
CREATE TRIGGER ddlTestEvents
ON DATABASE
FOR DDL_VIEW_EVENTS
AS
PRINT 'You must disable Trigger "ddlTestEvents" to drop, create or alter Views!'
ROLLBACK;
GO
After that I would check the sys.triggers and sys.trigger_events views to see what was inserted
SELECT name,te.type,te.type_desc
FROM sys.triggers t
JOIN sys.trigger_events te on t.object_id = te.object_id
WHERE t.parent_class=0
AND name IN('ddlTestEvents')
ORDER BY te.type,te.type_desc
In this case 3 rows were inserted
DDL_VIEW_EVENTS
----------------------------------
41 CREATE_VIEW
42 ALTER_VIEW
43 DROP_VIEW
Then I altered the trigger as follows
CREATE TRIGGER ddlTestEvents
ON DATABASE
FOR DDL_USER_EVENTS
AS
PRINT 'You must disable Trigger "ddlTestEvents" to drop, create or alter Users!'
ROLLBACK;
GO
I checked again with the same query
SELECT name,te.type,te.type_desc
FROM sys.triggers t
JOIN sys.trigger_events te on t.object_id = te.object_id
WHERE t.parent_class=0
AND name IN('ddlTestEvents')
ORDER BY te.type,te.type_desc
in this case 3 rows were also inserted
DDL_USER_EVENTS
----------------------------------
131 CREATE_USER
132 ALTER_USER
133 DROP_USER
I kept repeating this until I had all the events and below is the result
The number that you see before the event is the type from the sys.trigger_events view
DDL_XML_SCHEMA_COLLECTION_EVENTS
----------------------------------
177 CREATE_XML_SCHEMA_COLLECTION
178 ALTER_XML_SCHEMA_COLLECTION
179 DROP_XML_SCHEMA_COLLECTION
DDL_VIEW_EVENTS
----------------------------------
41 CREATE_VIEW
42 ALTER_VIEW
43 DROP_VIEW
DDL_TRIGGER_EVENTS
----------------------------------
71 CREATE_TRIGGER
72 ALTER_TRIGGER
73 DROP_TRIGGER
DDL_USER_EVENTS
----------------------------------
131 CREATE_USER
132 ALTER_USER
133 DROP_USER
DDL_TYPE_EVENTS
----------------------------------
91 CREATE_TYPE
93 DROP_TYPE
DDL_TABLE_EVENTS
----------------------------------
21 CREATE_TABLE
22 ALTER_TABLE
23 DROP_TABLE
DDL_SYNONYM_EVENTS
----------------------------------
34 CREATE_SYNONYM
36 DROP_SYNONYM
DDL_STATISTICS_EVENTS
-----------------------------------
27 CREATE_STATISTICS
28 UPDATE_STATISTICS
29 DROP_STATISTICS
DDL_SERVICE_EVENTS
------------------------------------
161 CREATE_SERVICE
162 ALTER_SERVICE
163 DROP_SERVICE
DDL_SCHEMA_EVENTS
------------------------------------
141 CREATE_SCHEMA
142 ALTER_SCHEMA
143 DROP_SCHEMA
DDL_ROUTE_EVENTS
------------------------------------
164 CREATE_ROUTE
165 ALTER_ROUTE
166 DROP_ROUTE
DDL_ROLE_EVENTS
----------------------------------
134 CREATE_ROLE
135 ALTER_ROLE
136 DROP_ROLE
DDL_REMOTE_SERVICE_BINDING_EVENTS
-----------------------------------
174 CREATE_REMOTE_SERVICE_BINDING
175 ALTER_REMOTE_SERVICE_BINDING
176 DROP_REMOTE_SERVICE_BINDING
DDL_QUEUE_EVENTS
---------------------------------
157 CREATE_QUEUE
158 ALTER_QUEUE
159 DROP_QUEUE
DDL_PROCEDURE_EVENTS
----------------------------------
51 CREATE_PROCEDURE
52 ALTER_PROCEDURE
53 DROP_PROCEDURE
DDL_PARTITION_SCHEME_EVENTS
------------------------------------
194 CREATE_PARTITION_SCHEME
195 ALTER_PARTITION_SCHEME
196 DROP_PARTITION_SCHEME
DDL_PARTITION_FUNCTION_EVENTS
------------------------------
191 CREATE_PARTITION_FUNCTION
192 ALTER_PARTITION_FUNCTION
193 DROP_PARTITION_FUNCTION
DDL_EVENT_NOTIFICATION_EVENTS
----------------------------------
74 CREATE_EVENT_NOTIFICATION
76 DROP_EVENT_NOTIFICATION
DDL_ASSEMBLY_EVENTS
-----------------------------------
101 CREATE_ASSEMBLY
102 ALTER_ASSEMBLY
103 DROP_ASSEMBLY
DDL_CONTRACT_EVENTS
-----------------------------------
154 CREATE_CONTRACT
156 DROP_CONTRACT
DDL_FUNCTION_EVENTS
---------------------------------
61 CREATE_FUNCTION
62 ALTER_FUNCTION
63 DROP_FUNCTION
DDL_INDEX_EVENTS
---------------------------------
24 CREATE_INDEX
25 ALTER_INDEX
26 DROP_INDEX
206 CREATE_XML_INDEX
DDL_MESSAGE_TYPE_EVENTS
------------------------------------
151 CREATE_MESSAGE_TYPE
152 ALTER_MESSAGE_TYPE
153 DROP_MESSAGE_TYPE
I promised that I would find out all the events that you can combine for example DDL_VIEW_EVENTS instead of CREATE_VIEW
,ALTER_VIEW and DROP_VIEW
So I finally did it, I created a bunch of triggers and then checked with a query that joined sys.triggers and sys.trigger_events
I started by creating a trigger and I used DDL_VIEW_EVENTS
CREATE TRIGGER ddlTestEvents
ON DATABASE
FOR DDL_VIEW_EVENTS
AS
PRINT 'You must disable Trigger "ddlTestEvents" to drop, create or alter Views!'
ROLLBACK;
GO
After that I would check the sys.triggers and sys.trigger_events views to see what was inserted
SELECT name,te.type,te.type_desc
FROM sys.triggers t
JOIN sys.trigger_events te on t.object_id = te.object_id
WHERE t.parent_class=0
AND name IN('ddlTestEvents')
ORDER BY te.type,te.type_desc
In this case 3 rows were inserted
DDL_VIEW_EVENTS
----------------------------------
41 CREATE_VIEW
42 ALTER_VIEW
43 DROP_VIEW
Then I altered the trigger as follows
CREATE TRIGGER ddlTestEvents
ON DATABASE
FOR DDL_USER_EVENTS
AS
PRINT 'You must disable Trigger "ddlTestEvents" to drop, create or alter Users!'
ROLLBACK;
GO
I checked again with the same query
SELECT name,te.type,te.type_desc
FROM sys.triggers t
JOIN sys.trigger_events te on t.object_id = te.object_id
WHERE t.parent_class=0
AND name IN('ddlTestEvents')
ORDER BY te.type,te.type_desc
in this case 3 rows were also inserted
DDL_USER_EVENTS
----------------------------------
131 CREATE_USER
132 ALTER_USER
133 DROP_USER
I kept repeating this until I had all the events and below is the result
The number that you see before the event is the type from the sys.trigger_events view
DDL_XML_SCHEMA_COLLECTION_EVENTS
----------------------------------
177 CREATE_XML_SCHEMA_COLLECTION
178 ALTER_XML_SCHEMA_COLLECTION
179 DROP_XML_SCHEMA_COLLECTION
DDL_VIEW_EVENTS
----------------------------------
41 CREATE_VIEW
42 ALTER_VIEW
43 DROP_VIEW
DDL_TRIGGER_EVENTS
----------------------------------
71 CREATE_TRIGGER
72 ALTER_TRIGGER
73 DROP_TRIGGER
DDL_USER_EVENTS
----------------------------------
131 CREATE_USER
132 ALTER_USER
133 DROP_USER
DDL_TYPE_EVENTS
----------------------------------
91 CREATE_TYPE
93 DROP_TYPE
DDL_TABLE_EVENTS
----------------------------------
21 CREATE_TABLE
22 ALTER_TABLE
23 DROP_TABLE
DDL_SYNONYM_EVENTS
----------------------------------
34 CREATE_SYNONYM
36 DROP_SYNONYM
DDL_STATISTICS_EVENTS
-----------------------------------
27 CREATE_STATISTICS
28 UPDATE_STATISTICS
29 DROP_STATISTICS
DDL_SERVICE_EVENTS
------------------------------------
161 CREATE_SERVICE
162 ALTER_SERVICE
163 DROP_SERVICE
DDL_SCHEMA_EVENTS
------------------------------------
141 CREATE_SCHEMA
142 ALTER_SCHEMA
143 DROP_SCHEMA
DDL_ROUTE_EVENTS
------------------------------------
164 CREATE_ROUTE
165 ALTER_ROUTE
166 DROP_ROUTE
DDL_ROLE_EVENTS
----------------------------------
134 CREATE_ROLE
135 ALTER_ROLE
136 DROP_ROLE
DDL_REMOTE_SERVICE_BINDING_EVENTS
-----------------------------------
174 CREATE_REMOTE_SERVICE_BINDING
175 ALTER_REMOTE_SERVICE_BINDING
176 DROP_REMOTE_SERVICE_BINDING
DDL_QUEUE_EVENTS
---------------------------------
157 CREATE_QUEUE
158 ALTER_QUEUE
159 DROP_QUEUE
DDL_PROCEDURE_EVENTS
----------------------------------
51 CREATE_PROCEDURE
52 ALTER_PROCEDURE
53 DROP_PROCEDURE
DDL_PARTITION_SCHEME_EVENTS
------------------------------------
194 CREATE_PARTITION_SCHEME
195 ALTER_PARTITION_SCHEME
196 DROP_PARTITION_SCHEME
DDL_PARTITION_FUNCTION_EVENTS
------------------------------
191 CREATE_PARTITION_FUNCTION
192 ALTER_PARTITION_FUNCTION
193 DROP_PARTITION_FUNCTION
DDL_EVENT_NOTIFICATION_EVENTS
----------------------------------
74 CREATE_EVENT_NOTIFICATION
76 DROP_EVENT_NOTIFICATION
DDL_ASSEMBLY_EVENTS
-----------------------------------
101 CREATE_ASSEMBLY
102 ALTER_ASSEMBLY
103 DROP_ASSEMBLY
DDL_CONTRACT_EVENTS
-----------------------------------
154 CREATE_CONTRACT
156 DROP_CONTRACT
DDL_FUNCTION_EVENTS
---------------------------------
61 CREATE_FUNCTION
62 ALTER_FUNCTION
63 DROP_FUNCTION
DDL_INDEX_EVENTS
---------------------------------
24 CREATE_INDEX
25 ALTER_INDEX
26 DROP_INDEX
206 CREATE_XML_INDEX
DDL_MESSAGE_TYPE_EVENTS
------------------------------------
151 CREATE_MESSAGE_TYPE
152 ALTER_MESSAGE_TYPE
153 DROP_MESSAGE_TYPE
Thursday, August 17, 2006
Architecting Microsoft.com – SQL Server Podcast And Video
Channel 9 has an interesting video and podcast about the microsoft.com architecture with SQL Server
From the site: "At the heart of most web sites once you dig down below the routers, below the web servers, below the ASP.NET code you find a critical piece. The heart of the matter if you will is the database and if that heart stops... well let’s just say your website will assume room temperature quickly. The question is; what do the guys at Microsoft.com do to insure that the heart of the system is thumpin’ and pumpin’ day in and day out 24x7 while still needing to do updates, patches, server maintenance etc.? Well never fear because we have the answer for you so listen up and learn something!"
The podcast is available in WMA and MP3 formats and runs for 27 minutes and 55 seconds
The video length is 26 minutes and 9 seconds
you can get the podcast and the video here (http://channel9.msdn.com/Showpost.aspx?postid=226519)
From the site: "At the heart of most web sites once you dig down below the routers, below the web servers, below the ASP.NET code you find a critical piece. The heart of the matter if you will is the database and if that heart stops... well let’s just say your website will assume room temperature quickly. The question is; what do the guys at Microsoft.com do to insure that the heart of the system is thumpin’ and pumpin’ day in and day out 24x7 while still needing to do updates, patches, server maintenance etc.? Well never fear because we have the answer for you so listen up and learn something!"
The podcast is available in WMA and MP3 formats and runs for 27 minutes and 55 seconds
The video length is 26 minutes and 9 seconds
you can get the podcast and the video here (http://channel9.msdn.com/Showpost.aspx?postid=226519)
Wednesday, August 16, 2006
Query Multiple Databases
"Query Multiple Databases"
This search term has been used 13 times in the last week on this blog. So here is a little blog post about it
It's really not complicated to query multiple databases. You have to have permissions on both databases
The syntax looks like this:
SELECT *
FROM Database1.ObjectOwner.TableName
JOIN Database2.ObjectOwner.TableName ON.....
So here is a little script so that you can test it out
USE master
GO
--Create the first Database
CREATE DATABASE DBtest1
GO
--Create the second Database
CREATE DATABASE DBtest2
GO
USE DBtest1
GO
--Create Table1 on DBtest1
CREATE TABLE Table1(id INT, DescriptionValue VARCHAR(49))
INSERT Table1 VALUES (1,'DBtest1')
GO
USE DBtest2
GO
--Create Table2 on DBtest2
CREATE TABLE Table2(id INT, DescriptionValue VARCHAR(49))
INSERT Table2 VALUES (1,'DBtest2')
GO
USE master
GO
--Do the join between DBtest1 and DBtest2
SELECT *
FROM DBtest1.dbo.Table1 t1
JOIN DBtest2.dbo.Table2 t2 ON t1.id = t2.id
GO
--Another way
SELECT *
FROM DBtest1..Table1 t1
JOIN DBtest2..Table2 t2 ON t1.id = t2.id
GO
--Drop these databases
DROP DATABASE DBtest1,DBtest2
This search term has been used 13 times in the last week on this blog. So here is a little blog post about it
It's really not complicated to query multiple databases. You have to have permissions on both databases
The syntax looks like this:
SELECT *
FROM Database1.ObjectOwner.TableName
JOIN Database2.ObjectOwner.TableName ON.....
So here is a little script so that you can test it out
USE master
GO
--Create the first Database
CREATE DATABASE DBtest1
GO
--Create the second Database
CREATE DATABASE DBtest2
GO
USE DBtest1
GO
--Create Table1 on DBtest1
CREATE TABLE Table1(id INT, DescriptionValue VARCHAR(49))
INSERT Table1 VALUES (1,'DBtest1')
GO
USE DBtest2
GO
--Create Table2 on DBtest2
CREATE TABLE Table2(id INT, DescriptionValue VARCHAR(49))
INSERT Table2 VALUES (1,'DBtest2')
GO
USE master
GO
--Do the join between DBtest1 and DBtest2
SELECT *
FROM DBtest1.dbo.Table1 t1
JOIN DBtest2.dbo.Table2 t2 ON t1.id = t2.id
GO
--Another way
SELECT *
FROM DBtest1..Table1 t1
JOIN DBtest2..Table2 t2 ON t1.id = t2.id
GO
--Drop these databases
DROP DATABASE DBtest1,DBtest2
Monday, August 14, 2006
Analysis Services Stored Procedure Project Released On CodePlex
The Analysis Services Stored Procedure project is a set of sample stored procedures for Analysis Services 2005. These samples have been written in C# and sample MDX queries are included that demonstrate the use of the procedures against the Adventure Works DW sample database. It was developed by a group of community volunteers with 2 main aims in mind:
To provide a set of useful extensions to Analysis Services 2005.
To provide a variety of example source code for people looking to write their own stored procedures.
Visit the CodePlex site to download the source code
To provide a set of useful extensions to Analysis Services 2005.
To provide a variety of example source code for people looking to write their own stored procedures.
Visit the CodePlex site to download the source code
Friday, August 11, 2006
Use The Sieve of Eratosthenes To Find All PrimeNumbers Below 1 Million
In mathematics, the Sieve of Eratosthenes is a simple, ancient algorithm for finding all prime numbers up to a specified integer. It was created by Eratosthenes, an ancient Greek mathematician. Wheel factorization is often applied on the list of integers to be checked for primality, before Sieve of Eratosthenes is used, to increase the speed.
Algorithm
Write a list of numbers from 2 to the largest number you want to test for primality. Call this List A. (This is the list of squares on the left-hand-side of the picture.)
Write the number 2, the first prime number, in another list for primes found. Call this List B. (This is the list on the right-hand-side of the picture.)
Strike off 2 and all multiples of 2 from List A.
The first remaining number in the list is a prime number. Write this number into List B.
Strike off this number and all multiples of this number from List A. The crossing-off of multiples can be started at the square of the number, as lower multiples have already been crossed out in previous steps.
Repeat steps 4 through 6 until no more numbers are left in List A.
Read more on Wikipedia
So here is the SQL Version, it runs in 7 seconds on my machine when I run it a
second time, first run is 16 seconds
Algorithm
Write a list of numbers from 2 to the largest number you want to test for primality. Call this List A. (This is the list of squares on the left-hand-side of the picture.)
Write the number 2, the first prime number, in another list for primes found. Call this List B. (This is the list on the right-hand-side of the picture.)
Strike off 2 and all multiples of 2 from List A.
The first remaining number in the list is a prime number. Write this number into List B.
Strike off this number and all multiples of this number from List A. The crossing-off of multiples can be started at the square of the number, as lower multiples have already been crossed out in previous steps.
Repeat steps 4 through 6 until no more numbers are left in List A.
Read more on Wikipedia
So here is the SQL Version, it runs in 7 seconds on my machine when I run it a
second time, first run is 16 seconds
SET NOCOUNT ON
DECLARE @i INT
-- Create a 10-digit table
DECLARE @D TABLE (N INT)
INSERT INTO @D (N)
SELECT 0 UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4
INSERT INTO @D (N)
SELECT N+5 FROM @D
-- build a small sieve table between 2 and 1000
DECLARE @T TABLE (N INT)
INSERT INTO @T( N )
SELECT 1+A.N+10*(B.N+10*C.N)
FROM @D A, @D B, @D C
DELETE FROM @T WHERE N = 1
SET @I = 2
WHILE @I <= SQRT(1000)
BEGIN
DELETE FROM @T WHERE N % @I = 0 AND N > @I
SET @I = @I + 1
END
-- Create large table between 1001 and 1000000
SELECT A+10*(B+10*(C+10*(D+10*(E+ 10*F)))) AS N
INTO #P
FROM
( SELECT A.N AS A, B.N AS B, C.N AS C, D.N AS D, E.N AS E, F.N AS F
FROM @D A, @D B, @D C, @D D, @D E, @D F
WHERE A.N in (1, 3, 7, 9) -- Not divisible by 2 or 5
) blah
WHERE (A+B+C+D+E+F) % 3 <> 0 -- Or 3
AND (A+3*B+2*C-D-3*E-2*F) % 7 <> 0 -- Or 7
AND (B-A+D-C+F-E) % 11 <> 0 -- Or 11
AND D|E|F <> 0 -- Don't include the first 1000 numbers,
--we already have these in the small sieve table
UNION ALL SELECT 1000000
-- sieve the big table with smaller one
SELECT @I = 2
WHILE @I IS NOT NULL
BEGIN
DELETE FROM #P WHERE N% @I = 0
SELECT @I = MIN(N) FROM @T WHERE N > @I
END
-- add primes up to 1000
INSERT INTO #P SELECT N FROM @T
-- Here are the results
--78498 rows
SELECT * FROM #P ORDER BY 1
drop table #P
go
Wednesday, August 09, 2006
Try Quest LiteSpeed And Win An iPod Nano (Hopefully)
Quest has a nice little give away. They are giving away 40 2GB Apple Nano iPods to people who are willing to try LiteSpeed for SQL Server.
I am already using LiteSpeed on the production machines but the cool thing is that Quest has a free version that you can use with the developer editions of SQL Server at no cost at all
So check it out here
I am already using LiteSpeed on the production machines but the cool thing is that Quest has a free version that you can use with the developer editions of SQL Server at no cost at all
So check it out here
Monday, August 07, 2006
SQL Server Book Sales Up 98% Compared To Last Year
Tim O’Reilly has posted his latest State of the Computer Book Market article. Here are 2 excerpts: “Looking at the Database rollup, we again see the strength of SQL Server, the decline of Oracle book sales, and that while MySQL is still a much larger category than Postgres, Postgres is showing some curious strength. This is one of the things that treemap visualizations are good for. Small, bright green categories stand out, and you can start paying closer attention. (Ruby also showed bright green while it was still a tiny category before its remarkable surge over the past year.) We also see the continuing popularity of personal databases like Access and Filemaker.
“
“A few high-level observations:
• C# book sales continues to gain on Java, with a 49% unit sales increase compared to Java's 10% decrease.
• Ruby continues its momentum, and is the fastest-growing programming language in terms of book sales.
• Microsoft's new release of SQL Server has continued to drive significant book sales, with that market up 86%. ASP.Net is also on a roll, with book sales up 61%.
“
Read the whole article here
“
“A few high-level observations:
• C# book sales continues to gain on Java, with a 49% unit sales increase compared to Java's 10% decrease.
• Ruby continues its momentum, and is the fastest-growing programming language in terms of book sales.
• Microsoft's new release of SQL Server has continued to drive significant book sales, with that market up 86%. ASP.Net is also on a roll, with book sales up 61%.
“
Read the whole article here
Thursday, August 03, 2006
Store The Output Of A Stored Procedure In A Table Without Creating A Table
I saw this technique in the Inside Microsoft SQL Server 2005: T-SQL Querying T-SQL and today I saw it also here The OPENROWSET Trick: Accessing Stored Procedure Output In A SELECT Statement @ Ward Pond's SQL Server blog
I decided to expand this a little
Sometimes I need to quickly find out who is blocking what (or what is blocking who for that matter) so I run sp_who2 then look at the BlkBy column and run a DBCC INPUTBUFFER or fn_get_sql to get the sql statement
When you have a lot of connections it's a pain in the neck to look for the BlkBy where it's not . since the result is ordered by SPID
You can always do
CREATE TABLE
INSERT TABLE
EXEC Proc
But who wants to create tables all the time (not me, at least not for this stuff)
SPID is twice in the resultset of sp_who2 (who know why?) so that complicates things a little
So let's start with sp_who
SELECT * INTO #TempSpWho
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off exec master.dbo.sp_who')
--return only the connections to master
SELECT * FROM #TempSpWho
WHERE dbname ='master'
--Let's try sp_who2
SELECT * INTO #TempSpWho2
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off exec master.dbo.sp_who2')
--Oops
Server: Msg 2705, Level 16, State 3, Line 1
Column names in each table must be unique. Column name 'SPID' in table '#TempSpWho2' is specified more than once.
--No problem list the columns
SELECT SPID, Status, Login, HostName, BlkBy,DBName, Command, CPUTime, DiskIO, LastBatch, ProgramName
INTO #TempSpWho2
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off exec master.dbo.sp_who2')
--Get the connections to master only
SELECT * FROM #TempSpWho2
WHERE dbname ='master'
--Get the blocking SPID's
SELECT * FROM #TempSpWho2
WHERE BlkBy NOT LIKE '% .'
--Get user connections only (everything with a SPID below 51 is reserved for sql server processes)
SELECT * FROM #TempSpWho2
WHERE SPID >= 50
A couple of notes
The OPENROWSET call opens a separate connection to SQL Server, so there is some overhead associated with this approach
This technique is not supported inside a declared transaction
Blocking can occure with a poorly architected stored procedure
I decided to expand this a little
Sometimes I need to quickly find out who is blocking what (or what is blocking who for that matter) so I run sp_who2 then look at the BlkBy column and run a DBCC INPUTBUFFER or fn_get_sql to get the sql statement
When you have a lot of connections it's a pain in the neck to look for the BlkBy where it's not . since the result is ordered by SPID
You can always do
CREATE TABLE
INSERT TABLE
EXEC Proc
But who wants to create tables all the time (not me, at least not for this stuff)
SPID is twice in the resultset of sp_who2 (who know why?) so that complicates things a little
So let's start with sp_who
SELECT * INTO #TempSpWho
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off exec master.dbo.sp_who')
--return only the connections to master
SELECT * FROM #TempSpWho
WHERE dbname ='master'
--Let's try sp_who2
SELECT * INTO #TempSpWho2
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off exec master.dbo.sp_who2')
--Oops
Server: Msg 2705, Level 16, State 3, Line 1
Column names in each table must be unique. Column name 'SPID' in table '#TempSpWho2' is specified more than once.
--No problem list the columns
SELECT SPID, Status, Login, HostName, BlkBy,DBName, Command, CPUTime, DiskIO, LastBatch, ProgramName
INTO #TempSpWho2
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off exec master.dbo.sp_who2')
--Get the connections to master only
SELECT * FROM #TempSpWho2
WHERE dbname ='master'
--Get the blocking SPID's
SELECT * FROM #TempSpWho2
WHERE BlkBy NOT LIKE '% .'
--Get user connections only (everything with a SPID below 51 is reserved for sql server processes)
SELECT * FROM #TempSpWho2
WHERE SPID >= 50
A couple of notes
The OPENROWSET call opens a separate connection to SQL Server, so there is some overhead associated with this approach
This technique is not supported inside a declared transaction
Blocking can occure with a poorly architected stored procedure
Wednesday, August 02, 2006
Top SQL Server Google Searches For July 2006
These are the top SQL Searches on this site for the month of July. I have left out searches that have nothing to do with SQL Server or programming. As you can see it has been a slow(er) month. And Google reports only searches that have been searched for more than once. For example if you have these 4 searches
insert triggers
insert trigger
insert triggers
insert trigger!
Then only insert triggers will show up since the other two were used only one time
Here are the results...
increase maximum row size in mssql
crystal report division by zero code
insert triggers
select sum where
select from
delete a null record
Let's talk about the last search (delete a null record ) a little bit
The code below will show you how exactly you delete a row with a NULL value. You can not use =NULL but you have to use IS NULL
CREATE TABLE #TestDeleteNull (id INT identity, SomeDate DATETIME)
INSERT #TestDeleteNull VALUES(GETDATE())
INSERT #TestDeleteNull VALUES(GETDATE())
INSERT #TestDeleteNull VALUES(NULL)
--Check what's in the table
SELECT * FROM #TestDeleteNull
--This won't work
DELETE #TestDeleteNull
WHERE SomeDate = NULL
--(0 row(s) affected)
--This is the way
DELETE #TestDeleteNull
WHERE SomeDate IS NULL
--(1 row(s) affected)
--Check again
SELECT * FROM #TestDeleteNull
insert triggers
insert trigger
insert triggers
insert trigger!
Then only insert triggers will show up since the other two were used only one time
Here are the results...
increase maximum row size in mssql
crystal report division by zero code
insert triggers
select sum where
select from
delete a null record
Let's talk about the last search (delete a null record ) a little bit
The code below will show you how exactly you delete a row with a NULL value. You can not use =NULL but you have to use IS NULL
CREATE TABLE #TestDeleteNull (id INT identity, SomeDate DATETIME)
INSERT #TestDeleteNull VALUES(GETDATE())
INSERT #TestDeleteNull VALUES(GETDATE())
INSERT #TestDeleteNull VALUES(NULL)
--Check what's in the table
SELECT * FROM #TestDeleteNull
--This won't work
DELETE #TestDeleteNull
WHERE SomeDate = NULL
--(0 row(s) affected)
--This is the way
DELETE #TestDeleteNull
WHERE SomeDate IS NULL
--(1 row(s) affected)
--Check again
SELECT * FROM #TestDeleteNull
Tuesday, August 01, 2006
6 Different Ways To Get The Current Identity Value From A Table
This article will show you how to get the current identity value from a table and also some things that might act a little different than you would expect
Let's first create our two simple tables
CREATE TABLE TestOne (id INT identity,SomeDate DATETIME)
CREATE TABLE TestTwo (id INT identity,TestOneID INT,SomeDate DATETIME)
--Let's insert 4 rows into the table
INSERT TestOne VALUES(GETDATE())
INSERT TestOne VALUES(GETDATE())
INSERT TestOne VALUES(GETDATE())
INSERT TestOne VALUES(GETDATE())
Here are 6 ways to check for the current value
--1 @@IDENTITY
SELECT @@IDENTITY
--this returns 4
--2 DBCC CHECKIDENT
DBCC CHECKIDENT (TestOne, NORESEED)
after running DBCC CHECKIDENT the message returned is
Checking identity information: current identity value '4', current column value '4'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
--3 MAX function
SELECT MAX(id)
FROM TestOne
you can also check with the MAX function but this is not recommended becuase you might get some other identity value that is not yours but from a different user
--4 TOP 1 and ORDER BY DESC
SELECT TOP 1 id
FROM TestOne
ORDER BY id DESC
--The same applies here as for the max function, this is not recommended
--5 IDENT_CURRENT
SELECT IDENT_CURRENT('TestOne')
--IDENT_CURRENT is another way to check
--6 SCOPE_IDENTITY
SELECT SCOPE_IDENTITY()
--This one is very similar to @@IDENTITY with one BIG difference (shown later)
--Let's add a trigger to the TestOne table
CREATE TRIGGER trTestOne ON [dbo].[TestOne]
FOR INSERT
AS
DECLARE @CreditUserID INT
SELECT @CreditUserID = (SELECT ID FROM Inserted)
INSERT TestTwo VALUES(@CreditUserID,GETDATE())
GO
--Let's insert another row into the TestOne table
INSERT TestOne VALUES(GETDATE())
SELECT @@IDENTITY --1
SELECT @@IDENTITY,SCOPE_IDENTITY(),IDENT_CURRENT('TestOne') --1,5,5
Now why doesn't @@IDENTITY return 5 but 1?
This is because @@IDENTITY doesn't care about scope and returns the last identity value from all the statements, which in this case is from the code within the trigger trTestOne
So the bottom line is this: Always use SCOPE_IDENTITY() unless you DO need the last identity value regradless of scope (for example you need to know the identity from the table insert inside the trigger)
--Clean up this mess
DROP TABLE TestOne,TestTwo
Let's first create our two simple tables
CREATE TABLE TestOne (id INT identity,SomeDate DATETIME)
CREATE TABLE TestTwo (id INT identity,TestOneID INT,SomeDate DATETIME)
--Let's insert 4 rows into the table
INSERT TestOne VALUES(GETDATE())
INSERT TestOne VALUES(GETDATE())
INSERT TestOne VALUES(GETDATE())
INSERT TestOne VALUES(GETDATE())
Here are 6 ways to check for the current value
--1 @@IDENTITY
SELECT @@IDENTITY
--this returns 4
--2 DBCC CHECKIDENT
DBCC CHECKIDENT (TestOne, NORESEED)
after running DBCC CHECKIDENT the message returned is
Checking identity information: current identity value '4', current column value '4'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
--3 MAX function
SELECT MAX(id)
FROM TestOne
you can also check with the MAX function but this is not recommended becuase you might get some other identity value that is not yours but from a different user
--4 TOP 1 and ORDER BY DESC
SELECT TOP 1 id
FROM TestOne
ORDER BY id DESC
--The same applies here as for the max function, this is not recommended
--5 IDENT_CURRENT
SELECT IDENT_CURRENT('TestOne')
--IDENT_CURRENT is another way to check
--6 SCOPE_IDENTITY
SELECT SCOPE_IDENTITY()
--This one is very similar to @@IDENTITY with one BIG difference (shown later)
--Let's add a trigger to the TestOne table
CREATE TRIGGER trTestOne ON [dbo].[TestOne]
FOR INSERT
AS
DECLARE @CreditUserID INT
SELECT @CreditUserID = (SELECT ID FROM Inserted)
INSERT TestTwo VALUES(@CreditUserID,GETDATE())
GO
--Let's insert another row into the TestOne table
INSERT TestOne VALUES(GETDATE())
SELECT @@IDENTITY --1
SELECT @@IDENTITY,SCOPE_IDENTITY(),IDENT_CURRENT('TestOne') --1,5,5
Now why doesn't @@IDENTITY return 5 but 1?
This is because @@IDENTITY doesn't care about scope and returns the last identity value from all the statements, which in this case is from the code within the trigger trTestOne
So the bottom line is this: Always use SCOPE_IDENTITY() unless you DO need the last identity value regradless of scope (for example you need to know the identity from the table insert inside the trigger)
--Clean up this mess
DROP TABLE TestOne,TestTwo
Subscribe to:
Posts (Atom)