Posted by Dan | Posted in Databases, SQL Server | Posted on 07-12-2011
0
If you’ve ever tried to delete two rows that are identical from SSMS, you may come across this little beauty:

To get around this, you have to delete 1 row at a time and use SET ROWCOUNT. So you would do something like
SET ROWCOUNT 1
GO
DELETE FROM users_to_optin WHERE email = 'someone@yahoo.com'
That would delete one record at a time, even if there were multiple instances of ’someone@yahoo.com’.
After you’re done, make sure you set the rowcount back to 0, which turns the limitation off.
Check out more about ROWCOUNT.
Posted by Dan | Posted in Databases, SQL Server | Posted on 06-08-2011
0
If you’re still stuck working with a SQL Server 2000 database, there’s no reason why you shouldn’t be using SSMS 2008 R2. There’s lots of great add-ons for it and provides a rich set of features, aside from merging Query Analyzer and Enteprise Manager.
One thing to watch out for, is that if you script out your database objects, while you’re connected to SQL Server 2000, by default, it will script out TSQL that is compatible only with SQL Server 2008. To switch this, there are two ways:
Tools -> Options -> SQL Server Object Explorer -> Scripting

Database -> Tasks -> Generate Scripts

Posted by Dan | Posted in Databases, SQL Server | Posted on 05-30-2011
0
I’ve always found the SSIS import tool a bit clunky. I tried to import a CSV file and it get crapping out before completing.
- Copying to [dbo].[export] (Stopped)
Messages
- ·Error 0xc02020a1: Data Flow Task 1: Data conversion failed. The data conversion for column “Email Address” returned status value 4 and status text “Text was truncated or one or more characters had no match in the target code page.”.
(SQL Server Import and Export Wizard)
- ·Error 0xc020902a: Data Flow Task 1: The “output column “Email Address” (10)” failed because truncation occurred, and the truncation row disposition on “output column “Email Address” (10)” specifies failure on truncation. A truncation error occurred on the specified object of the specified component.
(SQL Server Import and Export Wizard)
I sifted through the data, only a few hundred rows, and I could not see anything wrong with it. I made the columns the right type and increased the column size more than the largest number of characters in the fields. I searched Google and Microsoft Forums trying a handful of solutions and nothing worked.
So what did I do? I had enough and just opened the file from CSV, into Excel, resaved it as an Excel 2007. Re-ran the SSIS import wizard to open an Excel file instead of a CSV, and voila. I’m still baffled though, as to what exactly the problem is.
Posted by Dan | Posted in Databases, SQL Server | Posted on 06-07-2010
0
Here’s another way to created a linked server using another provider, Microsoft Jet 4.0 OLE DB Provider. This is for SQL Server 2008. Check out my previous Linked Server tutorial if needed for SQL Server 2005.

For this setup, let’s use the login’s current security context. Make sure that you whatever SSMS you use to connect to the server uses the same user credentials as user that created the linked server.

So if I create that on a server, then I’ll have query it using the same credentials just used. If you want to know how to query it, check out my Previous Tutorial.
Can’t stress enough how handy database snapshots (compatible only in Enterprise and Developer editions of SQL Server 2005+) come in when testing bulk imports, data scrubbing, or any sort of data / schema modification script. In nearly no time, I can create a snapshot (via shortcut snippet), run my script – don’t like the results? My script crapped out the data? I can run an instant undo by recovering from the snapshot, which works pretty fast. If I want to create another snapshot, I usually tend to overwrite the snapshot I created, and then create it again.
It’s so handy that I have a snippet for it:

Anywhoot, here’s how you create a snapshot:
1
2
3
4
5
6
7
| -- CREATING A SNAPSHOT
CREATE DATABASE YourDatabase_snap ON -- Name of new snapshot
(
NAME = yourdb_data, -- Logical filename of source db you want to snapshot
FILENAME = 'c:\YourDatabase_data_1800.ss' -- Sparse file to create
)
AS SNAPSHOT OF YourDatabase; -- Source db name |
1
2
3
4
| -- RECOVERING FROM A SNAPSHOT
USE master;
RESTORE DATABASE YourDatabase -- Source db name where the data resided
FROM DATABASE_SNAPSHOT = 'YourDatabase_snap'; -- Snapshot db name |
Deleting a snapshot is just like dropping a database.
1
| DROP DATABASE YourDatabase_Snap |
In my last project, there was a bit of data scrubbing on the database side (SQL Server 2008) that I decided to create a few UDF’s that function similar to ColdFusion’s Lists function. The one that varies a little bit is ListLen(), since I needed to take into account empty tokens. The ChopIf() was inspired by Perl’s chop() function. These UDFs should be SQL Server 2005-compatible.
I should say though, that some of these functions depend on each other. ListLen(), GetToken(), and ChopIf() are independent.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| ------------------------------------------------------------------
-- Functions similarly like ColdFusion ListSort() function,
-- except it currently only sorts strings.
--
-- Example 1:
-- dbo.ListSort( 'dan is so mega awesome that he rules all the time', 'ASC', ' ' )
--
-- Returns:
-- all awesome dan he is mega rules so that the time
--
-- Example 2:
-- dbo.ListSort( 'dan is so mega awesome that he rules all the time', 'DESC', ' ' )
--
-- Returns:
-- time the that so rules mega is he dan awesome all
------------------------------------------------------------------
CREATE FUNCTION [dbo].[ListSort]
(
@string VARCHAR(2000),
@sort_type CHAR(3) = 'ASC',
@delimiter VARCHAR(2000) = ','
)
RETURNS VARCHAR(500)
AS
BEGIN
DECLARE @position AS INT
DECLARE @token AS VARCHAR (2000)
DECLARE @counter AS INT
DECLARE @sortedList AS VARCHAR(500)
DECLARE @sortTempTable TABLE ( token VARCHAR(500) )
DECLARE @sortedTable TABLE ( token VARCHAR(500) )
SELECT @string = @string + @delimiter,
@counter = 1,
@position = 0,
@token = ''
WHILE ( PATINDEX( '%' + @delimiter + '%' , @string ) <> 0 )
BEGIN
SELECT @position = PATINDEX('%' + @delimiter + '%' , @string ),
@token = LEFT( @string, @position - 1 ),
@string = STUFF( @string, 1, @position, NULL ),
@counter = @counter + 1
INSERT @sortTempTable( token ) VALUES( @token )
END
SET @sortedList = ''
-- Let's sort the table and put it into @sortedTable
-- Because of nature of Rank(), we can't set @sortedList in this statement.
-- Have to separate it into another select clause.
INSERT INTO @sortedTable
SELECT LTRIM( token )
FROM @sortTempTable
ORDER BY CASE WHEN @sort_type = 'ASC' THEN ( RANK() OVER ( ORDER BY LTRIM(token) ASC ) )
WHEN @sort_type = 'DESC' THEN ( RANK() OVER ( ORDER BY LTRIM(token) DESC ) )
END
SELECT @sortedList = @sortedList + token + @delimiter
FROM @sortedTable
RETURN dbo.ChopIf( @sortedList, @delimiter )
END
GO |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| ------------------------------------------------------------------
-- Functions sort of like ColdFusion's ListLen() method, but it
-- takes into account empty tokens.
--
-- Example 1:
-- dbo.ListLen( 'Dan is cool', ' ' )
--
-- Returns:
-- 3
--
-- Example 2:
-- dbo.ListLen( 'dan,,very,,,,awesome,', ',' )
--
-- Returns:
-- 8
------------------------------------------------------------------
CREATE FUNCTION [dbo].[ListLen]
(
@string VARCHAR(2000),
@delimiter VARCHAR(2000) = ','
)
RETURNS INT
AS
BEGIN
DECLARE @loopCount INT,
@tokenCount INT
SELECT @loopCount = 0,
@tokenCount = 0
-- If it's an empty string, the list length is 0
IF DATALENGTH( @string ) = 0
BEGIN
SET @tokenCount = 0
END
ELSE
BEGIN
-- Count tokens, including empty ones like dan,,very,,,,awesome,
SET @tokenCount = @tokenCount + 1
WHILE ( @loopCount < DATALENGTH( @string ) )
BEGIN
IF SUBSTRING( @string, @loopCount, DATALENGTH( @delimiter ) ) = @delimiter
BEGIN
SET @tokenCount = @tokenCount + 1
END
SET @loopCount = @loopCount + 1
END
END
-- Handle extra count from space being delimiter
IF @delimiter = ' '
SET @tokenCount = @tokenCount - 1
-- If there's no token to the right of the last delimiter, then count that
-- as an empty token.
IF ( RIGHT( @string, 1 ) = @delimiter )
BEGIN
SET @tokenCount = @tokenCount + 1
END
RETURN @tokenCount
END
GO |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| ------------------------------------------------------------------
-- Functions like ColdFusion's ListLast()
-- Gets token value that's been separated by a delimiter.
--
-- Example:
-- dbo.ListLast( 'Dan is cool', ' ' )
--
-- Returns:
-- cool
------------------------------------------------------------------
CREATE FUNCTION [dbo].[ListLast]
(
@string VARCHAR(2000),
@delimiter VARCHAR(2000) = ','
)
RETURNS VARCHAR(2000)
AS
BEGIN
RETURN dbo.ListGetAt( @string, dbo.ListLen( @string, @delimiter ) , @delimiter )
END
GO |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| ------------------------------------------------------------------
-- Wrapper for GetToken() Function
-- Gets token value that's been separated by a delimiter.
--
-- Example:
-- dbo.ListGetAt( 'Dan is cool', 2, ' ' )
--
-- Returns:
-- is
------------------------------------------------------------------
CREATE FUNCTION [dbo].[ListGetAt]
(
@string VARCHAR(2000),
@token INT,
@delimiter VARCHAR(2000)
)
RETURNS VARCHAR(2000)
AS
BEGIN
RETURN dbo.GetToken( @string, @token, @delimiter )
END
GO |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| ------------------------------------------------------------------
-- Returns the first item in a tokenized list.
--
-- Example:
-- dbo.ListFirst( 'Dan is cool', ' ' )
--
-- Returns:
-- Dan
------------------------------------------------------------------
CREATE FUNCTION [dbo].[ListFirst]
(
@string VARCHAR(2000),
@delimiter VARCHAR(2000) = ','
)
RETURNS VARCHAR(2000)
AS
BEGIN
RETURN dbo.ListGetAt( @string, 1, @delimiter )
END
GO |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| ------------------------------------------------------------------
-- Functions similarly like ColdFusion GetToken() Function.
-- Gets token value that's been separated by a delimiter.
--
-- Example:
-- dbo.GetToken( 'Dan is cool', 2, ' ' )
--
-- Returns:
-- is
------------------------------------------------------------------
CREATE FUNCTION [dbo].[GetToken]
(
@string VARCHAR(2000),
@tokenPosition INT,
@delimiter VARCHAR(2000)
)
RETURNS VARCHAR(2000)
AS
BEGIN
DECLARE @position AS INT
DECLARE @token AS VARCHAR (2000)
DECLARE @counter AS INT
SELECT @string = @string + @delimiter,
@counter = 1,
@position = 0,
@token = ''
WHILE ( PATINDEX('%' + @delimiter + '%' , @string ) <> 0) AND ( @tokenPosition + 1 <> @counter )
BEGIN
SELECT @position = PATINDEX('%' + @delimiter + '%' , @string),
@token = LEFT(@string, @position-1),
@string = STUFF(@string, 1, @position, null),
@counter = @counter + 1
END
RETURN @token
END |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| ------------------------------------------------------------------
-- Chops the last character if it's @chopped
--
-- Example:
-- dbo.ChopIf( 'Dan is cool!', '!' )
--
-- Returns:
-- Dan is cool
------------------------------------------------------------------
CREATE FUNCTION [dbo].[ChopIf]
(
@string VARCHAR(2000),
@chopped VARCHAR(2000)
)
RETURNS VARCHAR(2000)
AS
BEGIN
IF ( RIGHT( @string, DATALENGTH(@chopped) ) = @chopped )
BEGIN
SET @string = LEFT( @string, DATALENGTH( @string ) - DATALENGTH( @chopped ) )
END
RETURN @string
END
GO |
Posted by Dan | Posted in Databases, SQL Server | Posted on 04-24-2010
0
I love this tool. It’s a free add-on if you own SQL Prompt, RedGate’s version of intellisense, which is better, in my eyes, than Microsoft’s. It uses SQL Prompt’s FTS collection to search for any piece of string in any DB object. It’s crazy fast. What I like the most though, is the ability to right click on a result, and move the focus to appropriate DB object in the explorer panel. Hit CTRL+ALT+D to trigger the search screen and start typing away.

Posted by Dan | Posted in Databases, SQL Server | Posted on 04-24-2010
0
I can’t say how many various problems I’ve had connecting to SQL Server. I’ve lost count at this point. This was the last one I had, which I’ve encountered a number of times and always successful to fix it.
Cannot connect to x.x.x.x.
Additional Information:
A network-related or instance-specific error occurred while establishing a connection to SQL Server….

Now usually when I encounter this error, I do something suggested here at Pinal Dave’s site. This time nothing mentioned there worked. What did work, was me explicitly selecting the Network protocol, and not leaving it as the :

Still wondering why I have to do this, as I’ve never had to explicitly select the protocol before, and nothing on the server has changed in years. Will continue to investigate.
Posted by Dan | Posted in Databases, SQL Server | Posted on 04-04-2010
0
Currently I use RedGate’s SQL Data Compare to see differences in data across databases. It’s a great product. One thing I love about RedGate is the usability of their products. All of them are intuitive and easy to use. What if you don’t have the cash to do this though?
You could use the EXCEPT (introduced in SQL Server 2005) clause to do your comparison. For example:
SELECT *
FROM #table2 -- returns 30 records
EXCEPT
SELECT *
FROM #table1 -- returns 10 records.
You get a result set of 20 records if those 10 records in the table1 statement are in table2. You can think of it as subtracting records from table2 that are in table1. You will get the end result of 20 records.
The following statement builds on that taking the end result and putting it back into table1. This is useful if you want to sync an outdated table (in this case table1) with another table that has additional records (table2).
INSERT INTO #table1
SELECT *
FROM #table2 -- latest data table (we'll be copying from here)
EXCEPT
SELECT *
FROM #table1 -- outdated table (has old data)
Other tools to compare data across tables: CompareData may let you do what you want, and its table compare is free unlimited, I believe, for the evaluation version. The great thing about this tool is also that it will check results of two SQL statements / stored procs. Useful when unit testing.
Also you can use TableDiff.exe in your “C:\Program Files\Microsoft SQL Server\90\COM” directory. Learn more about it at the SQL team website.
Winrar is a great tool used for compressing files. It also has a command line tool called “rar.exe” to compress files, in case you want to batch it up. Here’s an example of the most common switches I use.
"C:\Program Files\WinRAR\rar.exe" a -m5 -r -ep1 "C:\temp\Work\Upgrades\2010-02-06\111.rar" "C:\temp\Work\Upgrades\2010-02-06\Post-Upgrade\"
First path is the location of the rar file to create. The second path is either the location of the file(s) or directory to compress.
options used
-ep1 Exclude base directory from names
a Add files to archive
-r Recurse subdirectories (will compress entire directories)
-m5 Set compression level to maximum
You can even assign a password to it using the -p switch