I'm using two cursors in SQL Server 2008 R2 to work with two lists of values returned from Select statements. I read the first value from list tofind1 into a variable find1 and a value from list tosearch1 into a variable search1.
The underlying variable types in the tables are nvarchar of length 10 and 255 respectively. The variables are defined as the same length nvarchar.
I'm testing it with two strings similar to this:
find1 = 'bill'
search1 = 'bill,fred,mary'
When I try charindex(find1, search1) it returns 0. This is incorrect.
When I try charindex('bill',search1) it returns 1. This is correct.
When I just run the following code, both pairs of statements work fine:
DECLARE #search1 nvarchar(255);
DECLARE #find1 nvarchar(10);
set #find1 = 'bill'
set #search1 = 'bill,fred,mary'
select charindex(#find1,#search1)
select charindex('bill','bill,fred,mary')
if 'bill,fred,mary' like '%bill%'
print 'Yay'
if #search1 like '%' + #find1 + '%'
print 'Yes'
Is there something about selecting values into a cursor then assigning it to a variable that messes with its data type so CHARINDEX and LIKE won't work? I've trying using CAST functions to triply make sure that the variables are all seen as nvarchar.
Related
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.
In the query below, when I use the print statement the full query prints out as expected and I can pick it up and execute no problems. But if instead of printing it, I run it with EXEC, I get an error which
says incorrect syntax by taking some portion of the query and saying that it's an incorrect identifier, as if the executor just sees a partial query and not the full thing. As you can see, I am using varchar(max), which ought to fit the entire query string. Anyone have any ideas here? Thanks!
declare #RollUp varchar = "hello"
DECLARE #SQL VARCHAR(MAX)
SET #SQL =
'INSERT INTO #RESULT
SELECT CONVERT(VARCHAR,"[Member0].[MEMBER_CAPTION]") AS Zeroth,
CONVERT(VARCHAR,"[Member1].[MEMBER_CAPTION]") AS First,
CONVERT(VARCHAR,"[Member2].[MEMBER_CAPTION]") AS Second,
CONVERT(VARCHAR,"[Member3].[MEMBER_CAPTION]") AS Third,
CONVERT(VARCHAR,"[Member4].[MEMBER_CAPTION]") AS Fourth,
CONVERT(VARCHAR,"[Member5].[MEMBER_CAPTION]") AS Fifth,
CONVERT(VARCHAR,"[Member6].[MEMBER_CAPTION]") AS Sixth,
CONVERT(VARCHAR,"[Member7].[MEMBER_CAPTION]") AS Seventh,
CONVERT(MONEY,"[Measures].[MyMeasure]") AS Eighth
FROM OPENROWSET(''MSOLAP'',''DataSource=MyServer;Initial Catalog=Sales'' ,''
WITH MEMBER [Measures].[MyMeasure]
AS (SUM (StrToMember("[Trans Date].[Year - Quarter - Month - Date].[Month].&["+ Format(Now(),"yyyyMM") + "]").lag(12)
:StrToMember("[Trans Date].[Year - Quarter - Month - Date].[Month].&["+ Format(Now(),"yyyyMM") + "]").lag(1)
,[Measures].[Revenue]))
SELECT NON EMPTY([Measures].[MyMeasure]) on 0,
NON EMPTY({[Commission Category Current].[EP Business Line].[Business Line].members *
[Sales].[Product].members *
[Territory].[Territories].[Territory].members *
[Purchasing Site].[Customers].[Customer].members *
[Purchasing Site].[Cust ID].Children *
[Site].[Customers].[Customer].members *
[Site].[Cust ID].Children} *
[Territory].[Countries].[Territory RollUp].&[''' + #RollUp + ''']
) on 1 FROM SALES
)'''
DECLARE #SQL1 VARCHAR(MAX)= Replace(Replace(#SQL, '[''', '['), ''']', ']')
print #sql1
EXEC #SQL1
The table #Result is not known when you run exec. It is defined in the outer scope but not inherited in the inner scope. You cannot use temporary tables like this, unless they are global temporary tables (preceded by ## instead of just #).
Also, you should never use varchar() in SQL Server without a length. The default length depends on the context and might not be long enough. In other words, you should have a length for varchar() in the convert() statements.
I fixed by breaking up the query in 4 substrings, then at the end just do
EXEC (#STR1 + #STR2 + #STR3 + #STR4).
I'm not sure how a varchar(max) doesn't accept a dynamic string that is clearly not greater than 1000 characters long. Unless the editor is adding hidden chars.
In any event, fixed.
I want to do conversion in T-SQL from a varbinary type to string type
Here is an example :
First I got this varbinary
0x21232F297A57A5A743894A0E4A801FC3
And then I want to convert it to
21232f297a57a5a743894a0e4a801fc3
How to do this?
Try:
DECLARE #varbinaryField varbinary(max);
SET #varbinaryField = 0x21232F297A57A5A743894A0E4A801FC3;
SELECT CONVERT(varchar(max),#varbinaryField,2),
#varbinaryField
UPDATED:
For SQL Server 2008
I know this is an old question, but here is an alternative approach that I have found more useful in some situations. I believe the master.dbo.fn_varbintohexstr function has been available in SQL Server at least since SQL2K. Adding it here just for completeness. Some readers may also find it instructive to look at the source code of this function.
declare #source varbinary(max);
set #source = 0x21232F297A57A5A743894A0E4A801FC3;
select varbin_source = #source
,string_result = master.dbo.fn_varbintohexstr (#source)
If you want to convert a single VARBINARY value into VARCHAR (STRING) you can do by declaring a variable like this:
DECLARE #var VARBINARY(MAX)
SET #var = 0x21232F297A57A5A743894A0E4A801FC3
SELECT CAST(#var AS VARCHAR(MAX))
If you are trying to select from table column then you can do like this:
SELECT CAST(myBinaryCol AS VARCHAR(MAX))
FROM myTable
This works in both SQL 2005 and 2008:
declare #source varbinary(max);
set #source = 0x21232F297A57A5A743894A0E4A801FC3;
select cast('' as xml).value('xs:hexBinary(sql:variable("#source"))', 'varchar(max)');
I looked everywhere for an answer and finally this worked for me:
SELECT Lower(Substring(MASTER.dbo.Fn_varbintohexstr(0x21232F297A57A5A743894A0E4A801FC3), 3, 8000))
Outputs to (string):
21232f297a57a5a743894a0e4a801fc3
You can use it in your WHERE or JOIN conditions as well in case you want to compare/match varbinary records with strings
Here is a simple example I wrote to convert and convert back using the 2 convert methods, I also checked it with a fixed string
declare #VB1 VARBINARY(500),#VB2 VARBINARY(500),#VB3 VARBINARY(500)
declare #S1 VARCHAR(500)
SET #VB1=HASHBYTES('SHA1','Test')
SET #S1=CONVERT(varchar(500),#VB1,2)
SET #VB2=CONVERT(varbinary(500),#S1,2)
SET #VB3=CONVERT(varbinary(500),'640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA',2)
SELECT #VB1,#S1,#VB2,#VB3
IF #VB1=#VB2 PRINT 'They Match(2)'
IF #VB1=#VB3 PRINT 'They Match(3)'
PRINT str(Len(#VB1))
PRINT str(Len(#S1))
PRINT str(Len(#VB2))
SET #VB1=HASHBYTES('SHA1','Test')
SET #S1=CONVERT(varchar(500),#VB1,1)
SET #VB2=CONVERT(varbinary(500),#S1,1)
SELECT #VB1,#S1,#VB2
IF #VB1=#VB2 PRINT 'They Match(1)'
PRINT str(Len(#VB1))
PRINT str(Len(#S1))
PRINT str(Len(#VB2))
and the output
|||
0x640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA|640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA|0x640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA|0x640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA
(1 row(s) affected)
They Match(2)
They Match(3)
20
40
20
||
0x640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA|0x640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA|0x640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA
(1 row(s) affected)
They Match(1)
20
42
20
... Well, not exactly only for PRINT. I need to assign a string variable the value that mixes explicit substrings with integer values (and possibly with other type values). The goal is to get the string for logging.
So far, I use the code like:
DECLARE #msg nvarchar(1000)
...
SET #msg = #procname + 'result = ' + CAST(#result AS nvarchar(5))
+ '; error = ' + CAST(#error AS nvarchar(5))
where the #procname is a string like sp_my_proc:, and the #result and the #error are integer variables. The result should look like (no extra spaces around the numbers, just the minimum length):
sp_my_proc: result = 3; error = 0
The above approach works, but... Is there any better way for converting an integer variable to the string than CAST(#result AS nvarchar(5))? (Consider the magic number 5 being a minor detail to be ignored.)
How do you solve the problem of generating such strings in your code?
Thanks, Petr
In SQL-Server you can use STR() function
http://msdn.microsoft.com/ru-ru/library/ms189527.aspx
The default value for 'length' parameter is 10. Since an integer variable is never longer than 10 symbols (you'd have an overflow) this will always work without errors:
declare #test int
set #test = 333333333
select STR(#test)
Also, take a look at
String.Format like functionality in T-SQL?
I am using Parsename in SQL and would like to extract the last element in a list of items. I am using the following code.
Declare #string as varchar(1000)
set #string = '25.26.27.28'
SELECT PARSENAME(#string, 1)
This works and returns the value 28 as I expect. However if I expand my list past more than 4 items then the result returns a NULL. For example:
Declare #string2 as varchar(1000)
set #string2 = '25.26.27.28.29'
SELECT PARSENAME(#string2, 1)
I would expect this to return a value of 29 however only NULL is returned
I'm sure there is a simple explaination to this can anyone help?
PARSENAME is designed specifically to parse an sql object name. The number of periods in the latter example exempt it from being such a name so the call correctly fails.
Instead
select right(#string2, charindex('.', reverse(#string2), 1) - 1)
PARSENAME ( 'object_name' , object_piece )
'object_name'
Is the name of the object for which to retrieve the specified object part.
This name can have four parts: the server name, the database name, the owner name, and the object name.
If we give more than 4 parts, it will always return null.
For Ref: http://msdn.microsoft.com/en-us/library/ms188006.aspx