SQL Server Query with "ELSE:" - sql

I have various VB6 projects I'm maintaining with some of the queries being passed to the server having "ELSE:" with the colon used in case statements.
I'm wondering can someone tell me what the **ll the colon is used for? It causes errors in SQL2005 and greater, but SQL2000 works with no complaints.
I'd like to just remove it from the code & re-compile, but I'm afraid it'll break 10 other things in the application..
Thanks in advance...

Here is the deal.. somebody used the ELSE keyword as a LABEL in your code.
A word in TSQL followed by a colon is a Label. Here is a sample:
DECLARE #Count int
SET #Count = 0
ONE_MORE_TIME:
IF #Count <> 33
PRINT ‘Hello World’
SET #Count = #Count + 1
END
IF #Count <> GOTO ONE_MORE_TIME
In your case, the label might be "ELSE"
DECLARE #Count int
SET #Count = 0
ELSE:
IF #Count < 33
PRINT ‘Hello World’
SET #Count = #Count + 1
END
IF #Count < 33 GOTO ELSE
I have a feeling that this code is going to be badly indented as well. I'd almost be willing to put some money down on that.

why not remove it, recompile, and test the application to see what impact it may have?

Hmm, it causes errors in SQL2005?
In SQL server, ELSE is used in case statements to catch anything that hasn't been caught yet (it pertains to things that have "fallen through" all of the other cases). For example, suppose we'd like to list some items from a price database and categorize them with a custom 'Budget' text column, so for each item we'll look at it's price and set what it's 'Budget' value should be:
SELECT title, price,
Budget = CASE price
WHEN price > 20.00 THEN 'Expensive'
WHEN price BETWEEN 10.00 AND 19.99 THEN 'Moderate'
WHEN price < 10.00 THEN 'Inexpensive'
ELSE 'Unknown'
END,
FROM titles
The ELSE here catches everything that didn't really fall under "Expensive" or "Moderate" or "Inexpensive". Removing these ELSEs here will definitely mess your queries up.

Related

Generate short and Unique String values in SQL

I am building an application, which needs a unique identifier as a UserID (example A3D7sRt).
In my case i have instructed not to use numbers only UserID and It should be auto-generated. And also the user id should be 6-8 character long. This is because it has to be easily memorized.
Here using GUID is not an option for me. Because GUID is HEX in nature, so i will be getting less number of unique values compared to a string in the same length.
So what is the efficient way to do that in SQL? Also i do not want to run into frequent unique constraint failed exception.
This value is then used to login to the android mobile client. And no passwords in the login process.
Based on Martin Smith and Zohar Peled comments, I have found a solution.
Take a bigint (probably your primary key)
Encode it as BASE36
bigint must not be 0. Take higher number (or start from) to get
output length greater than 6 characters
Here is the T-SQL
DECLARE #Result VARCHAR(MAX) = ''
DECLARE #Val BIGINT = 101722230
IF (#Val <= 1000000)
BEGIN
Select 'Very Small ID Try With Large BIGINT'
return;
END
WHILE (#Val > 0)
BEGIN
SELECT #Result = CHAR(#Val % 36 + CASE WHEN #Val % 36 < 10 THEN 48 ELSE 55 END) + #Result,
#Val = FLOOR(#Val/36)
END
SElect #Result
Output
1OK9DI is the output for the above code. (Verified)
Thank you everyone who helped me by commenting to this question.

how to replace T-SQL CASE statement with efficient code

how can i replace the following case statement with efficient code
SELECT
CASE WHEN LEN(Code.Description)>=30
THEN left(Code.Description, 30) + '...'
ELSE NominalCode.Description END AS ShortDescription
FROM Code
Because the data set it returns is going to be 30-50,000 records and according to lead dev this code is ridiculous. I need help
Presumably, you intend:
SELECT (CASE WHEN LEN(c.Description) > 30
THEN left(c.Description, 30) + '...'
ELSE c.Description
END) AS ShortDescription
FROM Code c;
That is, the Description column references all come from the same table. Your code is fine.
However, I would adjust the semantics so the resulting string always has the same length:
SELECT (CASE WHEN LEN(c.Description) > 30
THEN LEFT(c.Description, 27) + '...'
ELSE c.Description
END) AS ShortDescription
FROM Code c;
Other than adding a ShortDesc field to your Product Table, perhaps I would try the following
Concat(left(Code.Description,30),IIF(Len(Code.Description)>30,'...',''))
or even
left(Code.Description,30)+IIF(Len(Code.Description)>30,'...','')
EDIT
As you can see the same execution plan, however, the performance of my approach was 18% better. This test was done on an isolated machine with a sample size of 30,000 records.

SQL Server : How to test if a string has only digit characters

I am working in SQL Server 2008. I am trying to test whether a string (varchar) has only digit characters (0-9). I know that the IS_NUMERIC function can give spurious results. (My data can possibly have $ signs, which should not pass the test.) So, I'm avoiding that function.
I already have a test to see if a string has any non-digit characters, i.e.,
some_column LIKE '%[^0123456789]%'
I would think that the only-digits test would be something similar, but I'm drawing a blank. Any ideas?
Use Not Like
where some_column NOT LIKE '%[^0-9]%'
Demo
declare #str varchar(50)='50'--'asdarew345'
select 1 where #str NOT LIKE '%[^0-9]%'
There is a system function called ISNUMERIC for SQL 2008 and up. An example:
SELECT myCol
FROM mTable
WHERE ISNUMERIC(myCol)<> 1;
I did a couple of quick tests and also looked further into the docs:
ISNUMERIC returns 1 when the input expression evaluates to a valid numeric data type; otherwise it returns 0.
Which means it is fairly predictable for example
-9879210433 would pass but 987921-0433 does not.
$9879210433 would pass but 9879210$433 does not.
So using this information you can weed out based on the list of valid currency symbols and + & - characters.
Solution:
where some_column NOT LIKE '%[^0-9]%'
Is correct.
Just one important note: Add validation for when the string column = '' (empty string). This scenario will return that '' is a valid number as well.
Method that will work. The way it is used above will not work.
declare #str varchar(50)='79136'
select
case
when #str LIKE replicate('[0-9]',LEN(#str)) then 1
else 0
end
declare #str2 varchar(50)='79D136'
select
case
when #str2 LIKE replicate('[0-9]',LEN(#str)) then 1
else 0
end
DECLARE #x int=1
declare #exit bit=1
WHILE #x<=len('123c') AND #exit=1
BEGIN
IF ascii(SUBSTRING('123c',#x,1)) BETWEEN 48 AND 57
BEGIN
set #x=#x+1
END
ELSE
BEGIN
SET #exit=0
PRINT 'string is not all numeric -:('
END
END
I was attempting to find strings with numbers ONLY, no punctuation or anything else. I finally found an answer that would work here.
Using PATINDEX('%[^0-9]%', some_column) = 0 allowed me to filter out everything but actual number strings.
The selected answer does not work.
declare #str varchar(50)='79D136'
select 1 where #str NOT LIKE '%[^0-9]%'
I don't have a solution but know of this potential pitfall. The same goes if you substitute the letter 'D' for 'E' which is scientific notation.

Dangling "else" Resolution in T-SQL

So I've been tasked with converting some T-SQL code to C code. Whoever wrote the code I'm converting indulged in little to no code etiquette. I know this because of the complete lack of commenting, lack of indentation, and lack of begin/end blocks except where absolutely syntactically necessary (and a few thrown in arbitrarily for good measure).
This raises a few problems. The code I'm converting is based on the Metaphone algorithm. I say "based on" because it has quite a few... "undocumented improvements" that make it differ from the official implementation. Because of this, I can't just go grab some Metaphone implementation, because then it wouldn't actually be a "correct" translation.
So here's the root of the issue(s):
if #str1='d'
if substring(#str,#cnt,3) in ('dge','dgy','dgi')
set #Result=#Result + 'j'
else
set #Result=#Result + 't'
Because of how Metaphone works, I'm pretty sure they meant:
if #str1='d'
if substring(#str,#cnt,3) in ('dge','dgy','dgi')
set #Result=#Result + 'j'
else
set #Result=#Result + 't'
But I'm not sure if it's actually being interpreted as:
if #str1='d'
if substring(#str,#cnt,3) in ('dge','dgy','dgi')
set #Result=#Result + 'j'
else
set #Result=#Result + 't'
This little snippet isn't too big of a deal, but just after it, there's a section with five "if" statements and only one "else" statement and with no begin/end blocks to explicitly arrange them. None of this would be a big deal if I could actually run the code to to test and see, but sadly, I don't have an environment to test it and nor do I have any output from previous usage of the code.
tl;dr: Do any of you T-SQL gurus out there know which of the above two statements it'll be interpreted as and what's the rule of them with shift/reduce conflicts in T-SQL? (Attach to first "if" statement, attach to last "if" statement, pick one at random?)
EDIT: Here's another fun one a few lines down.
if #str1='t'
if substring(#str,#cnt,3) in ('tia','tio')
set #Result=#Result + 'x'
else
if #str2='th'
set #Result=#Result + '0'
else
if substring(#str,#cnt,3) <> 'tch'
set #Result=#Result + 't'
EDIT2: Ok, if I'm reading these answers correctly, that means the above is actually
if #str1='t'
if substring(#str,#cnt,3) in ('tia','tio')
set #Result=#Result + 'x'
else
if #str2='th'
set #Result=#Result + '0'
else
if substring(#str,#cnt,3) <> 'tch'
set #Result=#Result + 't'
Here is something that should help you out
DECLARE #testvar INT;
DECLARE #testvar2 INT;
SET #testvar = 1;
SET #testvar2 = 1;
IF #testvar = 1
IF #testvar2 = 1
SELECT 'Got to 1';
ELSE
SELECT 'Got to 2';
If testvar and testvar2 are both 1, it outputs "Got to 1".
If testvar=1 and testvar2=2, it outputs "Got to 2".
If testvar=2, there is no output. So the else is getting paired off against the nearest if
Your assumption is correct.
IF () IF () X ELSE Y is equivilent to IF () BEGIN IF () X ELSE Y END
The ELSE keyword looks back to the most recent IF statement in the same scope. So to get what you think was intended, you need to add BEGIN and END statements...
IF (#str1='d')
BEGIN
IF (substring(#str,#cnt,3) in ('dge','dgy','dgi'))
SET #Result=#Result + 'j'
END
ELSE
SET #Result=#Result + 't'

How can I visualize the value of nvarchar(max), with max>65535, from SQL Server database? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
SQL Server Management Studio: Increase number of characters displayed in result set
Update: Note: that discussion contains INCORRECT answer marked as answer.
SSMS from SQL Server 2008 R2, permits to visualize maximum of 8192 characters in "Results to text" mode and 65535 in "Results to grid" mode. "Results to file" are also truncated.
How can I see the selected value of bigger size fast and cheap?
Update:
I saw previous discussion and the best answer is to create my own front-end app is not really an answer.
I am not planning to compete with DBMS client tools vendors.
I just need to see the value fast, dirty or cheap, be it tools or not tools.
I just cannot believe that in order to see a single value I should create client applications and there is no trick or way around.
Why don't you just return the dataset as XML and there are no size limitations? You can do this using the cast( COLUMN_NAME as XML ) to do this.
Quick and dirty, I like that. Of course it can be done from inside Management Studio, you just have to be little creative. The idea is simple - can't display the whole string? Chop it up and display more rows.
Here is a function that takes a varchar input and outputs table with chunks of specified size. You can then CROSS APLLY select from from original table with this function and get what you need.
Function:
create function Splitter( #string varchar(max), #pieceSize int )
returns #t table( S varchar(8000) )
as
begin
if ( #string is null or len(#string) = 0 )
return
set #pieceSize = isnull(#pieceSize, 1000)
if (#pieceSize < 0 or #pieceSize > 8000)
set #pieceSize = 8000
declare #i int = 0
declare #len int = len(#string)
while ( #i < #len / #pieceSize )
begin
insert into #t(S) values(substring( #string, #i * #pieceSize + 1, #pieceSize))
set #i = #i + 1
end
if (#len % #pieceSize) != 0
begin
if (#len / #pieceSize) = 0
set #i = 1
insert into #t(S) values(substring( #string, (#i - 1) * #pieceSize + 1, #len % #pieceSize ))
end
return
end
Usage example:
select t.ID, t.Col1, t.Col2, t.Col3, pieces.S
from dbo.MyTable as t
cross apply dbo.Splitter( t.MybigStringCol, 1000 ) as pieces
That is the problem, I attack in sqlise a PowerShell module of the SQLPSX codeplex project (sorry I'm only allowed to use on hyperlink please google for it).
PowerShell ISE is the Integrated Scripting Environment which is part of PowerShell V2.
SQLPSX is a collection of PowerShell modules targeting management and querying MS-SQLserver (and minimal support for ORACLE too).
The normal output-pane of ISE has some bad truncation/wrapping behaviour, but it is possible to send out-put to an editor pane.
When use a query that fetches a single row of a one column wide resultset and use either 'inline' or 'isetab' as output format, you get the complete varchar(max), text, CLOB (yes this works for ORACLE too) value.
If you query a single row with such columns, the result depends on embedded linefeeds, a width of 10000 chars / line is current set. But that is in a script language and you can modify it by yourself.
If you prefer a pure T-SQL solution, you can look a the source of my project Extreme T-SQL Script http://etsql.codeplex.com/. With the scripts print_string_in_lines.sql and sp_gentextupdate.sql you have the tools to generate update scripts to set fields to the current content. SQL-SERVER 2008 is required, as I internally use varchar(max).
BTW I don't have access to SQL Server 2008 R2. I though the limit is still about 4000 characters per text column.
I hope that helps
Bernd
Select
CASE WHEN T.TheSegment = 1 Then Cast(T.SomeID as varchar(50))
Else ''
End as The_ID
, T.ChoppedField
From (
Select SomeID
, 1 as TheSegment
, substring(SomeBigField, 1, 8000) as ChoppedField
from sometable
Union All
Select SomeID
, 2
, substring(SomeBigfield, 8001, 16000)
from sometable
) as t
order by t.SomeID, t.TheSegment;
Rinse and repeat if necessary on the unions or feel free to get recursive; not sure how much more than 16000 characters you feel like reading. About as cheap as it gets.
Many times these large fields contain formating characters, so the suggestions for creating your own form and using some type of richtext control are valid.
You can see it by viewing it in your front-end application. SSMS is not designed to be a general data viewer.