Convert an XML Variable Datatype to Relational Table Sql Server

0 comments

Posted on 10th February 2010 by admin in Scripts

, , , ,

***I’ve been having difficulty getting the code to display correctly. NOTE: the xml code is case sensitive! I’ve been trying to get all the bugs this lovely blog template is throwing at me, but I’m sorry if i miss some.***

This is an easy way to get xml into a relational table to work a little easier with other tables in the database. There are a few ways out there that produce the same result, but it seemed like this was the simplest to work with.

declare @xml xml
set @xml =
'~~?xml version="1.0" encoding=''UTF-8'' ?~~
    
        
        
        
        
        
    '
 select  c.value('@question[1]','varchar(255)') as Question
   ,c.value('@answer[1]','int') as Answer
 from @xml.nodes('//rows/item') as t(c)

Because of how the blog parses things, replace ~~ with the respective greater than or less than brackets.

The query is parsing everything for you and putting into a table. The example is using attributes for the query statement. Its a little easier on the eyes for me when trying to read what the results are expected to be, but I do not work with xml that much.

In the time I’ve been playing with it, it seems the default way is to use elements exclusively. As this example shows:

declare @xml xml
set @xml =
'~~?xml version="1.0" encoding=''UTF-8'' ?~~
    
        
            name1
            1
        
        
            name2
            2
        
        
            name3
            3
        
        
            name4
            4
        
        
            name5
            5
        
'
 select  c.value('question[1]','varchar(255)') as Question
   ,c.value('answer[1]','int') as Answer
 from @xml.nodes('//rows/Item') as t(c)

Besides the format change, the only thing that really changed in the query is I told it to look for elements. This is represented by the change from ‘@question[1]‘ to ‘question[1]‘. A small change, but this little small change can be really frustrating to try to figure out if you don’t know about it.

The just element route bugged me in trying to explain things, cuz everything I’ve been dealing with has a mix of elements and attributes. So getting confused on how to call it was the hardest step trying to reverse engineer my findings from internet blogs.The big thing to remember is attributes are called with an @ symbol before the attribute name, and the element is called with just the element name.

The value that is in the brackets is what date you are trying to grab. Since there is only one item in the tree, this makes it easy to grab the first dataset… I’m sorry if I’m giving bad terminology, I’m a little new towards what to properly call it.

If there is a situation where you want only the second dataset as this example:


    
        
            name1
            1
            name6
            6
        

Querying with the value of ‘question[2]‘ will return the Question:name6, answer:6 as a row in the table. However, with the limited playing I have done, i don’t know how to only tell it to go for the 2nd data set for a particular element. With the code as ‘question[2]‘, it is going to return all the second “Items.” Something to play around with for sure.

The data type after which attribute/element you are querying is what you need to convert to for the table to display. You want to make sure you have compatible data types. They use SQL data types, so stick to the minimal data types you are expecting.

To specify where you want to look in the xml, the @xml.nodes is where you do it. In the example above, I have the root as rows and the first element as Item. Can’t get much easier that that. :D

Get quick information on what queries are running on your SQL Server instance

0 comments

Posted on 2nd February 2010 by admin in Scripts

, , , , , , , , ,

This is for SQL Server 2005 and higher.

Whenever I need to get the queries that are currently running on the system, I tend to run this query first.

select
    r.session_id,
    r.start_time,
    r.status,
    r.command,
    db_name(r.database_id) as db,
    r.blocking_session_id,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    r.percent_complete,
    r.estimated_completion_time,
    r.cpu_time,
    r.total_elapsed_time,
    r.scheduler_id,
    r.reads,
    r.writes,
    r.logical_reads,
    r.row_count,
    r.granted_query_memory,
    case r.statement_end_offset
    when -1 then NULL
    else object_name(s2.objectid, s2.dbid)
    end,
    case r.statement_end_offset
    when -1 then s2.text
    else substring(s2.text, r.statement_start_offset/2, (r.statement_end_offset/2) - (r.statement_start_offset/2))
    end,
    s3.query_plan
from sys.dm_exec_requests r
    cross apply sys.dm_exec_sql_text(r.sql_handle) as s2
    cross apply sys.dm_exec_query_plan (r.plan_handle) as s3
where r.status <> 'background'
    and r.command <> 'task manager'
    and r.session_id <> @@SPID
    and r.database_id <> db_id('msdb')
order by r.cpu_time desc
        

It has a little more information than sp_who2 and gives you a rough idea of what is running at the time you execute this script. Running this script multiple times is probably going to return different results every time besides when nothing is running on the server. It’s light-weight and should not take longer than a second. The only time this script should be longer is when you have a serious problem going on with your system.

Now a lot of useful information is being presented here. Most are self explanatory, like the session_id or ‘Status’. However, this script helps in your initial investigation for blocking spids. The Wait_type/time/resource columns allow you to get an initial idea of the problem, and you can always look a little deeper in the sys.dm_os_waiting_tasks system view to get a better idea of the problem for blocks. Finding block reasons can turn into a whole post in it self, as that is not the only way to diagnose blocking spids. SQL Server provides lots of tools to find the necessary information.

Typically the Percent Complete and Estimated Completion Time are for tasks which provide how along the query is and what it is expected to finish. Usually it will be blank. The best example I can think of that uses those columns is when you are doing a backup for a database or when you are shrinking your database. Unfortunately the estimated completion time is Microsoft time… soo take it with a grain of salt. The percent complete is usually pretty accurate, but can be random on how fast it gets to 100%.

The next few columns are stats on the query you are running. It should be obvious with any of these columns, the higher the number, the worse off you are. The differences between reads and logical reads is the former is for physical HDD reads while the latter is for memory reads. Typically you want more logical reads than physical reads, but as always, the higher the number, the more intensive and a hog of the system resources it is. The highest number I’ve seen for logical reads is in the 100s of billions… That was an interesting day of doom.

Granted Query Memory is a column which shows how much memory has been devoted to this query. Since this is a count of pages for memory, you have to a do a little math to get an idea of how much memory is taken up in KB terms. I didn’t add the calculations to the query since I just know a high number can be doomy, but if you want to know the actually amount in terms of KiloBytes, here is the equation:

    (r.granted_query_memory *8060)/1024 as Granted_Query_Memory

A memory page has 8060 bytes of information after overhead, and dividing it by 1024 gets the number of kilobytes assigned to the memory page.

The next two columns provide some helpful information if they are provided. The first column is the object name (sproc/function) of the outer scope of the script running. The second is the sql script it is currently running to provide all the information. Usually the scope is what single script its running, but some times it pulls back the entire object script for you to figure out where the problem is.

The next column is the Query Plan. This guy is so full of information its great you have the ability to see it :D Its the actual execution plan the SQL Server Optimizer is using to run the query with. Since it is just an XML data type, there are two ways to view it. When you click it, it behaves differently depending on which version of SQL Server Management Studio you are using. SQL Server Management Studio 2008 and above see it as a SQL Plan and open it as such without any manipulation.

Unfortunately, it is not as easy in SQL Server Management Studio 2005. Upon opening the XML data type, it opens it in the default XML fashion. What you can do to get the visual representation is to save the file on your HDD. When saving, change the file name from XML to ‘.sqlplan’. Then you open the new sqlplan file and you get the graphical representation of the execution plan. This is an extra step for displaying the same information in the XML file, but its a lot smoother in SQL Server Management Studio 2008 and up.

Most of this information is coming from the system view sys.dm_exec_requests, with the sql text and plan coming from the system functions sys.dm_exec_sql_text and sys.dm_exec_query_plan. The where clauses filter out some of the common noise, but play with everything to get a better feel for what you need. This is the script I commonly use when working with a database problem. It’s scope is system wide, so you do not need to worry about being in a specific database.

This isn’t a script that will tell you everything, but gives a great way to start your investigation. I hope it does you well.

Getting the Row Count for a Sql Server Table

0 comments

Posted on 28th January 2010 by admin in Tips

, , , , , , , , , ,


Here are some methods I use to get the Row Count:

SELECT COUNT(1)
FROM dbo.[Table]

This has to be the simplest and most accurate way to get the Row Count. It is also the most intensive way since it has to do a table or clustered index scan to achieve the results. While not that bad for anything below a few million, anything above that it starts to get a little hectic. Trying to count a billion row table, it’ll take too long to get results and use up way to many resources.

This is for SQL Server 2000

As long as sysindexes and sysobjects are available tables in SQL server, this method will work. Currently it works up to version SQL Server 2008 R2, but that is no guarantee for the future. In moving to system views in later versions of SQL Server, you should use system views instead.

SELECT so.name AS [Table Name],
    rows AS [RowCount]
FROM sysindexes AS si
    join sysobjects AS so on si.id = so.id
WHERE indid IN (0,1)
    AND xtype = 'U'

Remember, these are not accurate counts, but give the best estimate on the server besides physically counting it with the first script provided above. While they aren’t accurate, they are damn close. One of these days, I’ll have to play around with huge tables to see how accurate these counts really are.
An indid of 0 means there are no indexes on the table and it is a heap table. An indid of 1 is the first index on the table. Usually this is the clustered index. You can query sysindexes or sys.indexes in future versions to figure out what index has an id of 1 if you want to know which index is being used for the row count.

The xtype where clause only gets the row counts for any user created tables. If you want to get a row count of the system tables as well, you can modify the where clause to the following:

WHERE si.indid IN (0,1)
    AND si.xtype in ('U','S')

This is for SQL Server 2005 and above

SELECT SUM(rows) as RowCount,
    OBJECT_NAME(OBJECT_ID) as [Table Name]
FROM sys.partitions as p
WHERE index_id in (0,1)
GROUP BY OBJECT_ID

Mostly the same code, but in a different place. It gets a rough count and actually lets me know a rough idea of how many rows are in every table of that database. According to Sql Server Books Online, this is only an approximate row count, so keep that in mind if basing any mission critical scripts off of it. While only an approximate, it does provide you with a good sense of how big the table is. The reason for including the where clause for index_id is because you want to make sure you are only geting a single count for each table. sys.partitions keeps count on all of the indexes and partitions for a particular table.

Including SUM(rows) is for when you are working with Sql Server Enterprise Edition. Enterprise Edition allows you to partition tables for better availability. When you partition a table, sys.partitions keeps an approximate number of how many rows are in each partition. Since we only want the row count, we want to add up all the partitions to get that close approximate count of the table.

Since sys.partitions has a scope of the the current database, you have to be a little fancy in getting the Row Count if you want to get all of the table’s row counts.

IF (OBJECT_ID('Tempdb..##Temp') is not null)
    DROP TABLE ##Temp

CREATE TABLE ##Temp (
    DatabaseName varchar(255),
    TableName varchar(255),
    [RowCount] bigint
)

INSERT INTO ##Temp (
    DatabaseName,
    TableName,
    [RowCount]
)
EXEC sp_MSforeachdb @command1 = 'USE ?;
SELECT ''?'' AS [Database Name],
    OBJECT_NAME(OBJECT_ID) as [Table Name],
    SUM(rows) as [Row Count]
FROM sys.partitions AS p
WHERE index_id in (0,1)
    AND DB_ID() > 4
GROUP BY OBJECT_ID'

SELECT DatabaseName,
    TableName,
    [RowCount]
FROM ##Temp

DROP TABLE ##Temp

This method of putting the results into a temp table allows you to work with the data easier. If you ran the sp_MSForeachdb sproc without this method, it would spit out a result set for every database on your server. The temp table brings it all back in one table and one result set. Every time the sproc changes database, the scope of a regular temp table is lost thus why you need the global temp table. Remember to clean up after you are done working with the global temp table, as it will stay around as long as a user is connected and using that table. Drop it as soon as you are finished with it so nothing else is tempted to use it.

I added an extra where clause in the statement to not get the row counts of the system databases which default to the database ids starting from 1. You can remove that line to get all the table counts, but the only values that will really change are the row counts of TempDB and possibly after a system update.

You can also use the SQL Server 2000 script, provided here, with the sp_MSforeachdb sproc to get all the row counts in the system on a SQL Server 2000 server.

In SQL Server Management Studio 2008, you don’t have to even code at all! Connecting to a server of SQL Server 2005 and above allows you to see the row count with relative ease. When connected to a server, press F7 or using the menu View -> Object Explorer Details. Click to the database you want to view, then to the tables list. This should provided you with the row count of every table! If I’m mistaken and that is not the default view, right click on the header and select “Row Count.” There’s also a lot more information there than Management Studio 2005, so play around.

Row Count in Management Studio 2008

Hope this helps you find the row count to tables faster :D

Hello world!

1 comment

Posted on 27th January 2010 by admin in Uncategorized

Ooo the sites set up to what i think is right… I hope it is… that would make things better for me.

I just need to figure out a better sleep schedule.

I wonder how easy this is going to be…

let me try something out:

<pre name="code" class="c-sharp">
... some code here ...
</pre>
SELECT
    SUM(rows) as RowCount,
    OBJECT_NAME(OBJECT_ID) as ObjectName,
FROM sys.Partitions
WHERE index_id in (0,1)
GROUP BY OBJECT_ID

wee… Note to self… be careful going between visual/html.

- Zielyn

*Edit… Forgot to add the where clause of index_id in (0,1) to make sure it only gets either heaps or the first index. Don’t need to count all the index partitions… that would just be silly.