Search

Thursday, January 6, 2011

Generate Numbers Between two Numbers in SQL Server

I was working on a query where I had generate numbers between two numbers in the shortest possible way. Here’s how to do it. In this example, we will be generating all the numbers between 10 and 18 (inclusive of both) using a quick and dirty way
SELECT DISTINCT numberFROM master..spt_valuesWHERE numberBETWEEN 10 AND 18
As I said, we needed a quick way to generate numbers. If you are looking for Production ready code, check this article here Creating a Number table in T-SQL which offers various ways of generating numbers, including a nice one from Itzik Ben-Gan.

Fixing 2537 Corruption Errors in SQL Server Reported by DBCC CHECKDB

Microsoft SQL Server is one of the most widely accepted RDBMS (Relational Database Management System), developed and marketed by Microsoft Corporation. It stores your mission-critical data in a database, which has two major data files - MDF (Master Database File) and NDF (Next Database File). In some situations, the SQL Server database may encounter inconsistency issues and become inaccessible. This behavior renders your precious data inaccessible and causes serious data loss. In order to overcome such issues, you need to go for SQL database recovery alternatives.

Microsoft SQL Server provides DBCC CHECKDB tool for checking the consistency and integrity of the database. It may report the inconsistency of the database if all the below mentioned conditions are true:

  • MS SQL Server loads the data to any column with sql_variant data type.

  • There are some character values in sql_variant column.

  • The information is sent either to another SQL Server directory or through intermediate file.

  • The information develops in some other column with sql_variant data type, and simultaneously it is sent by SQL Server on-the-wire.

The DBCC CHECKDB statement may report you the following corruption error:

“Msg 2537, Level 16, State 43, Server MYSERVER, Line 1 Table error: Object ID 1977058079, index ID 0, page (1:75), row 0. Record check (Valid SqlVariant) failed. Values are 4 and 0. DBCC results for 'MyTable'. There are 0 rows in 1 pages for object 'MyTable'. CHECKDB found 0 allocation errors and 1 consistency errors in table 'MyTable' (object ID 1977058079). CHECKDB found 0 allocation errors and 1 consistency errors in database 'MyReproDest'. repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKDB (MyReproDest ).”

Cause:

This problem occurs due to corruption of the Microsoft SQL Server database table or entire database. You should not run the REPAIR_ALLOW_DATALOSS statement on such databases as it may remove the affected data.

Resolution:

In order to recover SQL Server database in such cases, you should try restoring the database from updated backup. Backup is the easiest and the most effective way to prevent data loss.

However, in case backup is not updated or available, commercial SQL Serverrecovery software becomes need of hour. The advanced third-party tools enable you to scan entire database using powerful MS SQL recovery scanning algorithms and restore entire database.

Wednesday, January 5, 2011

Loading XML Data into SQL Server

With XML becoming more and more the rage, DBAs are seeing many more requests to deal with XML data files. The question is: how do you load the data in the XML file into a table in SQL Server?

The XML File
For the purposes of this article, let's use a small XML file that is readily available on the Internet. W3Schools.com has such a sample file at http://www.w3schools.com/XML/cd_catalog.xml. As you might surmise by the name of the file, it contains brief information about a CD catalog. Please download and save this file to your computer. I am going to assume that this is being saved in the C:\SQL folder, and that you are keeping the file name the same (cd_catalog.xml). If you change any of this, make appropriate changes to the code below.

The structure of the XML file is as follows. Note that there are multiple tags.

<CATALOG>

<CD>
<TITLE>Empire BurlesqueTITLE>
<ARTIST>Bob DylanARTIST>
<COUNTRY>USACOUNTRY>
<COMPANY>ColumbiaCOMPANY>
<PRICE>10.90PRICE>
<YEAR>1985YEAR>
CD>
CATALOG>

The Database
Let's just keep this short and simple. We will load this file into one table, with an identical structure as that of the XML file.

CREATE TABLE dbo.CD_Info (

Title
varchar(100),
Artist
varchar(100),
Country
varchar(25),
Company
varchar(100),
Price
numeric(5,2),
YearReleased
smallint);

Load the file into a staging table

We will be utilizing the OpenRowset function to bulk load the file into a staging table. First, we will create a staging table with one column of the XML data type. We will then load the file into this column. Note that use of the OpenRowset function requires a table alias.

DECLARE @CD TABLE (XMLData XML);

INSERT INTO @CD
SELECT *
FROM OPENROWSET(BULK N'C:\SQL\cd_catalog.xml', SINGLE_BLOB) rs;

Retrieve the data from the staging table

Next we will retrieve the data from the staging table, and "shred" the XML into its columns. One key thing to note about XML: regardless of the case sensitivity of your server/database, XML commands are always case sensitive. In the sample file, all of the XML tags are in upper case, so everything we need to do needs to be in upper case also.

This command will retrieve each element of each CD in the sample file:

SELECT Title = x.data.value('TITLE[1]','varchar(100)'),

Artist
= x.data.value('ARTIST[1]','varchar(100)'),
Country
= x.data.value('COUNTRY[1]','varchar(25)'),
Company
= x.data.value('COMPANY[1]','varchar(100)'),
Price
= x.data.value('PRICE[1]','numeric(5,2)'),
YearReleased
= x.data.value('YEAR[1]','smallint')
FROM @CD t
CROSS APPLY t.XMLData.nodes('/CATALOG/CD') x(data);

Note in this command the nodes and value functions. These are XML functions. The nodes function specifies the path to the data that you will be using, and it requires an alias. You then apply the value function to the alias to retrieve the specific data that you want. In the value function, you need to supply the element as a singleton expression, and the data type.

The CROSS APPLY will apply each row in the staging table to the XML nodes function. For more information on how the CROSS APPLY works, I refer you to these articles:
Understanding and Using Apply, Part 1: http://www.sqlservercentral.com/articles/APPLY/69953/
Understanding and Using Apply, Part 2: http://www.sqlservercentral.com/articles/APPLY/69954/

Inserting the data into the CD_Info table

At this point, inserting the data is very simple: just put an insert statement in front of the above select statement.

DECLARE @CD TABLE (XMLData XML);

INSERT INTO @CD
SELECT *
FROM OPENROWSET(BULK N'C:\SQL\cd_catalog.xml', SINGLE_BLOB) rs;

INSERT INTO dbo.CD_Info (Title, Artist, Country, Company, Price, YearReleased)
SELECT Title = x.data.value('TITLE[1]','varchar(100)'),
Artist
= x.data.value('ARTIST[1]','varchar(100)'),
Country
= x.data.value('COUNTRY[1]','varchar(25)'),
Company
= x.data.value('COMPANY[1]','varchar(100)'),
Price
= x.data.value('PRICE[1]','numeric(5,2)'),
YearReleased
= x.data.value('YEAR[1]','smallint')
FROM @CD t
CROSS APPLY t.XMLData.nodes('/CATALOG/CD') x(data);
SELECT *
FROM dbo.CD_Info;

References

OpenRowset: http://msdn.microsoft.com/en-us/library/ms190312.aspx
Value(), Nodes() and OpenXML(): http://msdn.microsoft.com/en-us/library/bb522645.aspx

Out-of-range and Invalid Data Causes Errors in SQL Server Database

Are you getting out-of-range or invalid data errors while accessing Microsoft SQL Server database? When you create a table in MS SQL Server, you need to specify the data types, size, and type of values that you can store in particular table. In case you store invalid data in any table, you may face this problem. The problem can also occur if database table is damaged and SQL Server application is unable to read it. This behavior causes data inaccessibility and data loss. At this stage, you are required to opt for SQL database recovery to work around the problem. Out-of-range or invalid data might get stored in Microsoft SQL Server database table in the older versions for any of the below reasons: Invalid data is passed by RPC (Remote Procedure Call) event calls made to MS SQL Server. Invalid data is presented in source when you use bulk-insert mechanisms, like bcp tool. Other possible reasons of data corrupt has left the table values in invalid sate. In case you have out-of-range, invalid, or corrupt data in any column of SQL Server database table, you may come across issues depending upon type of the operations you perform against invalid data. But, it is possible to hide invalid data. It is not discovered until the DBCC CHECKTABLE or DBCC CHECKDB command is not executed on Microsoft SQL Server database. If there are some invalid data in SQL Server database table, you may come across the following symptoms: When you run any queries against problem column of the table, you run across access violations and various other exceptions. Problems or errors when the statistics are created against affected table columns. Queries give incorrect results while running against the problem column. You encounter error messages similar to the following ones: “Msg 9100, Level 23, State 2, Line 1 Possible index corruption detected. Run DBCC CHECKDB.” In all such cases, SQL Server recovery becomes need of hour. To recover SQL Server database, you must have a valid and updated backup. Otherwise, you are required to use third-party applications, called MS SQL recovery software. SQL recovery applications are designed to carry out systematic scan of entire SQL Server database and extract all inaccessible data from it. They offer easy and safe recovery with simple user interface and read-only conduct. Stellar Phoenix SQL Recovery is the most efficient and widely used utility to ensure absolute recovery in all corruption scenarios. The software recovers corrupt databases of Microsoft SQL Server 2008, 2005, 2000, and 7.0. It repairs and restores both MDF and NDF files of SQL Server database.

Tuesday, January 4, 2011

How To Calculate the Number of Week Days Between two Dates

If the start date and end date are both week days, then the total number of week days in between is simply:
(total difference in days) - (total difference in weeks) * 2

or
DateDiff(dd, @start, @end) - DateDiff(ww, @start, @end)*2

... since the DateDiff() function with weeks returns the number of week "boundaries" that are crossed; i.e., the number of weekends.

If you have a table of holidays, then you can simply subtract them out as well:
DateDiff(dd, @start, @end) -
DateDiff(ww, @start, @end)*2 -
(select count(*) from holidays where holiday_date between @start and @end)

Now, what if the start day or the end day is on a weekend? In that case, you need to define what to do in those situations in your requirements.

For example, if the start date is Sunday, Nov 20th, and the end day is Monday, Nov 21st -- how many week days are between those dates? There's no universal correct answer; it could be 0, or 1, or perhaps even "undefined" (null) depending on your needs.