<facedesk>
So, I’ve been answering questions on StackOverflow for two days now, and I still like the experience. However, I have noticed a disturbing trend in several of the questions being asked that involve SQL Server. Here’s an example of one; I’ll give you the question, and my answer, and then tell you what’s bugging me.
TSQL Generate 5 character length string, all digits [0-9] that doesn’t already exist in database
What’s the best way to do this?
I need to generate a 5 digit length string where all the characters are numeric. However, I need to be able to do this ‘x’ amount of times (user variable) and store this random strings in a database. Furthermore, I can’t generate the same string twice. Old strings will be removed after 6 months.
Pseudo-code
DECLARE @intIterator INT, @intMax SET @intIterator = 1SET @intMax = 5 (number of strings to generate) WHILE @intIterator <= @intMax BEGIN -- GENERATE RANDOM STRING OF 5 NUMERIC DIGITS ??? -- INSERT INTO DB IF DOESN'T ALREADY EXIST INSERT INTO TSTRINGS SELECT @RANDOMSTRING IF @@ERROR = 0 SET @intIterator = @intIterator + 1 ENDI know this probably isn’t the best way to do it, so advice is appreciated. But really looking for ideas on how to generate the numeric 5 length strings.
I think this is a great question; the guy’s obviously looking for a list of randomly generated five-character strings comprised entirely of digits; this means there are only 100,000 possibilities. This question is tagged as SQL and TSQL, which means that he’s looking for a database-driven solution (I’m aware that there are several ways to skin this cat; I’m just showing you that he’s specifically looking for a SQL solution). Note, however, that he’s using a loop to create, validate, and insert 1 row at a time.
Here’s where a lot of reading lately on numbers tables comes into play; I think about this a bit, and post the following solution:
Here’s a set-based approach, using SQL 2005 syntax (would be a little easier with SQL 2008, but you didn’t specify). Also, if you had a numbers table, a large chunk of it can be cut out.
No looping, no duplicates, and should be nearly instantaneous (assuming the target column is indexed).
DECLARE @intMax INTEGER
SET @intMax = 5
INSERT INTO TSTRINGS
SELECT q.nString
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY ( NEWID() ) ) AS N2 ,
RIGHT(REPLICATE(’0′, 5) + CONVERT(VARCHAR(5), N), 5) AS nString
FROM –the subquery below could be replaced by a numbers table
( SELECT TOP 100000
ROW_NUMBER() OVER ( ORDER BY ( ac1.Object_ID ) ) – 1 AS N
FROM Master.sys.columns ac1
CROSS JOIN Master.sys.columns ac2
CROSS JOIN Master.sys.columns ac3
) numbers
WHERE RIGHT(REPLICATE(’0′, 5) + CONVERT(VARCHAR(5), N), 5) NOT IN ( SELECT nString
FROM TSTRINGS ) –check to see if reused
) q
WHERE q.N2 <= @intMax
A nice, tidy, set-based solution that I’ll probably keep in mind for generating passwords in the future (with a little work). So, what’s bugging me? Is it the fact that I have 0 votes for this solution? No, that’s not really it, because votes are kind of whimsical; some times you get them; sometimes you don’t.
No, what bugs me, is that out of the 6 answers posted, 3 of them involve CURSORS. For a SQL question. I know. Shock and horror.
Seriously, though; why do people still use cursors? I know that there are times when cursors are an appropriate tool, but you shouldn’t use them everyday. It’s kind of like buying those specialized drill bits for removing a stripped screw; for that specific application, they work great. If you leave them in your drill, and you try to use them in an everyday situation; guess what? You’ve stripped out a screw.
Let me be as clear as I can:
CURSORS SUCK, PEOPLE. HEAR ME? THEY SUCK.
There you go; I feel better now.
October 8, 2009
·
stuart ·
3 Comments
Posted in: SQL, SQLServerPedia Syndication







3 Responses
It’s simple: they haven’t made the paradigm shift.
Boy, you were quick! I was still cleaning up the code after it posted funny, and you’ve already replied
It just amazes me the number of posts that I’ve seen on there that the author thinks they need to do a cursor, and even more amazing is that people offer them cursor-based solutions. I understand when dealing with legacy code that you have to get dirty sometimes, but this is a prime question looking for a set-based solution.
Sheesh.
Tell us how you REALLY feel.
Leave a Reply