How to hold values in variable in sql server - sql-server

I need to fetch max length of First_name and put it into #sq i am getting an error.
Declare #sq nvarchar(max)
Set #sq=''
SELECT MAX(LEN(FIRST_NAME)) FROM #table1
Drop table #t
SELECT CASE WHEN LEN(SEQ_NUM) = 0 THEN NULL ELSE SEQ_NUM END AS REC_NUM,
CASE WHEN LEN(FIRST_NAME) = 0 THEN NULL ELSE CONVERT(CHAR(Select #sq)),RTRIM(UPPER(FIRST_NAME))) END AS FIRST_NAME
into #t
from #tabel1

There's a few problem with this SQL. If we start with the first statement:
Set #sq=''SELECT MAX(LEN(FIRST_NAME)) FROM #table1
You have a couple of wayward single quotes here ('); not sure what they're doing. Secondly, if you're assigning a variables value from a dataset, the syntax is SELECT {Variable} = {expression} [,{Variable} = {expression} [,...]] FROM {etc} Thus you get:
SELECT #sq = MAX(LEN(FIRST_NAME))
FROM #table1;
The next statement, well, that's a mess. Firstly, there's also a wayward right parenthesis ()) here: RTRIM(UPPER(FIRST_NAME))) There should only be 2.
The expression CONVERT(CHAR(Select #sq)) is very wrong. CONVERT require 2 parameters, but only has one, and CHAR would return an character for the appropriate number provided. I.e. CHAR(65) returns A. I suspect you mean CONVERT(char,#sq) (you should really be declaring a length here!), however, #sq is already an nvarchar(max) (which is also pointless, as it's being assigned the value of an int). Thus I literally have no idea what you're trying to achieve here.

You need to assign the variable, like this:
Declare #sq int --LEN returns an int, not a varchar!
SELECT #sq = MAX(LEN(FIRST_NAME))
FROM #table1

Related

How to check IS NULL in dynamic query in sql server

I did following store procedure using dynamic query, see the following blueprint of code
ALTER PROCEDURE [dbo].[usp_Report] (
#LocationId INT = NULL
,#UserId INT = NULL)
DECLARE #miscquery NVARCHAR (MAX);
begin
SET #miscquery='
SELECT
,A.AgreementNumber AS Contract
,A.AgreementId
FROM tblAgreement A
WHERE
AND (A.IsDeleted = 0 or A.IsDeleted is null)
AND (
(
' + convert(NVARCHAR(30), #LocationId) + ' IS NULL
AND (
A.CheckoutLocation IN (
SELECT LocationId
FROM [dbo].[tblUserLocations]
WHERE UserID = ' + convert(VARCHAR(10), #userId) +'
AND IsDeleted = 0
)
OR A.CheckoutLocation IS NULL
)
)
OR A.CheckoutLocation = ' + convert(VARCHAR(10), #LocationId) +'
)'
EXEC (#miscquery)
end
)
here when i execute the query with #Locationid is null, results doesn't return table, it returns like following
(63 rows affected)
(2325 rows affected)
please help me. thank you
The code you have there cannot be your actual code, firstly because right at the start you try to set a variable called #miscquery before you declare it. There's also no reason for this code to be dynamic, so it's clear you're doing some other stuff as well.
I will take it as a given that for some reason you "need" dynamic SQL. I will put in the standard warning about sanitising your inputs. That was it.
OK. Even if #miscquery had been declared, the code as written will not produce any results. It will either throw a syntax error, or do nothing, depending on your setting for concat_null_yields_null.
Let's take the likely case: you have the default setting for this, which means that when you concatenate a varchar to null, the result is null.
Observe the following code:
declare #locationId int = null;
select 'this sentence ends with...' + convert(nvarchar(30), #locationId);
What will be the output?
"This sentence ends with... null"
"This sentence ends with..."
null
The answer is 3. And notice: that's not a string with the value "null". That's just null. When you convert the null value to a string, you don't get a string with the value "null", you get the null value.
OK, so now we try to add null to the end of our string. When you try to concatenate the null value to a string with the + operator, the entire result is null.
Therefore, your entire #miscquery variable is null at the end of the assignment.
So what you are then doing is the same as this:
declare #myquery varchar(max) = null;
exec sp_executesql #myquery
Which is valid, and doesn't throw any error, but does nothing. Then the rest of your code does whatever it does, and produces the results you see.
if concat_null_yields_null was set to off then you would get a syntax error, because the resulting text would not be valid SQL when you handed it to sp_executesql.
As Dan said, the best and safest solution would be to parameterize your inputs. But putting that aside, the solution you need would look something like the following. In the iif() function, I look at the value of #locationId. If it is null, then I want the string "null". If it is not null, then I want the string conversion of whatever value it has.
declare #locationId int = null;
declare #query varchar(max) =
'select * from mytable where '
+ iif(#locationId is null, 'null', convert(nvarchar(30), #locationId))
+ ' is null';
print #query;

SQL isnull fails with try_cast

I am trying to handle some data in the following way.
If the entry is numeric, cast it as an integer.
If the entry is not numeric, keep it as it is.
I am using 'try_cast' to cast my numeric entries to my integers. This gives NULL if the entry is not numeric.
declare #code varchar(3) = 'fff'
select try_cast(#code as int) as code
I then thought, well if I catch the null with an isnull I will be able to output the original value as I wanted.
declare #code varchar(3) = 'fff'
select isnull( try_cast(#code as int), #code) as code
However I get a conversion failed error.
I did not expect this behavior. Why is this happening and how can I acheive the desired behaviour?
TRY_CAST(... as int) return INT data type,
ISNULL(INT, VARCHAR(3)) leads both to INT
ISNULL: Returns the same type as check_expression.
declare #code varchar(3) = '123'
select ISNULL(CAST(try_cast(#code as int) as VARCHAR(3)),#code ) as code
may use
COALESCE: Returns the data type of expression with the highest data type
precedence
but INT upper VARCHAR in
Data type precedence
You are having a type-conversion error, because of the incompatibility. The column is either an integer or a string, but not both.
When you have two types in an expression, the numeric one dominates. In other words, SQL Server attempts to convert the string value to a number. Of course, this fails when done implicitly when try_convert() fails.
I would suggest two columns:
select try_cast(#code as int) as int_code, #code as orig_code
This is a block of code within a larger body of code, yes? As in, you're not trying to have a function dynamically return different data types based on the input?
If so, can you use sql_variant_property via an if-else block to direct flow of control? e.g.
declare #code varchar(3) = 'fff'
if SQL_VARIANT_PROPERTY(#code,'BaseType') = 'INT'
begin
print 'do numeric comparison'
end
else
begin
print 'do string comparison'
end

SQL Server : converting varchar to INT

I am stuck on converting a varchar column UserID to INT. I know, please don't ask why this UserID column was not created as INT initially, long story.
So I tried this, but it doesn't work. and give me an error:
select CAST(userID AS int) from audit
Error:
Conversion failed when converting the varchar value
'1581............................................................................................................................' to data type int.
I did select len(userID) from audit and it returns 128 characters, which are not spaces.
I tried to detect ASCII characters for those trailing after the ID number and ASCII value = 0.
I have also tried LTRIM, RTRIM, and replace char(0) with '', but does not work.
The only way it works when I tell the fixed number of character like this below, but UserID is not always 4 characters.
select CAST(LEFT(userID, 4) AS int) from audit
You could try updating the table to get rid of these characters:
UPDATE dbo.[audit]
SET UserID = REPLACE(UserID, CHAR(0), '')
WHERE CHARINDEX(CHAR(0), UserID) > 0;
But then you'll also need to fix whatever is putting this bad data into the table in the first place. In the meantime perhaps try:
SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), ''))
FROM dbo.[audit];
But that is not a long term solution. Fix the data (and the data type while you're at it). If you can't fix the data type immediately, then you can quickly find the culprit by adding a check constraint:
ALTER TABLE dbo.[audit]
ADD CONSTRAINT do_not_allow_stupid_data
CHECK (CHARINDEX(CHAR(0), UserID) = 0);
EDIT
Ok, so that is definitely a 4-digit integer followed by six instances of CHAR(0). And the workaround I posted definitely works for me:
DECLARE #foo TABLE(UserID VARCHAR(32));
INSERT #foo SELECT 0x31353831000000000000;
-- this succeeds:
SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), '')) FROM #foo;
-- this fails:
SELECT CONVERT(INT, UserID) FROM #foo;
Please confirm that this code on its own (well, the first SELECT, anyway) works for you. If it does then the error you are getting is from a different non-numeric character in a different row (and if it doesn't then perhaps you have a build where a particular bug hasn't been fixed). To try and narrow it down you can take random values from the following query and then loop through the characters:
SELECT UserID, CONVERT(VARBINARY(32), UserID)
FROM dbo.[audit]
WHERE UserID LIKE '%[^0-9]%';
So take a random row, and then paste the output into a query like this:
DECLARE #x VARCHAR(32), #i INT;
SET #x = CONVERT(VARCHAR(32), 0x...); -- paste the value here
SET #i = 1;
WHILE #i <= LEN(#x)
BEGIN
PRINT RTRIM(#i) + ' = ' + RTRIM(ASCII(SUBSTRING(#x, #i, 1)))
SET #i = #i + 1;
END
This may take some trial and error before you encounter a row that fails for some other reason than CHAR(0) - since you can't really filter out the rows that contain CHAR(0) because they could contain CHAR(0) and CHAR(something else). For all we know you have values in the table like:
SELECT '15' + CHAR(9) + '23' + CHAR(0);
...which also can't be converted to an integer, whether you've replaced CHAR(0) or not.
I know you don't want to hear it, but I am really glad this is painful for people, because now they have more war stories to push back when people make very poor decisions about data types.
This question has got 91,000 views so perhaps many people are looking for a more generic solution to the issue in the title "error converting varchar to INT"
If you are on SQL Server 2012+ one way of handling this invalid data is to use TRY_CAST
SELECT TRY_CAST (userID AS INT)
FROM audit
On previous versions you could use
SELECT CASE
WHEN ISNUMERIC(RTRIM(userID) + '.0e0') = 1
AND LEN(userID) <= 11
THEN CAST(userID AS INT)
END
FROM audit
Both return NULL if the value cannot be cast.
In the specific case that you have in your question with known bad values I would use the following however.
CAST(REPLACE(userID COLLATE Latin1_General_Bin, CHAR(0),'') AS INT)
Trying to replace the null character is often problematic except if using a binary collation.
This is more for someone Searching for a result, than the original post-er. This worked for me...
declare #value varchar(max) = 'sad';
select sum(cast(iif(isnumeric(#value) = 1, #value, 0) as bigint));
returns 0
declare #value varchar(max) = '3';
select sum(cast(iif(isnumeric(#value) = 1, #value, 0) as bigint));
returns 3
I would try triming the number to see what you get:
select len(rtrim(ltrim(userid))) from audit
if that return the correct value then just do:
select convert(int, rtrim(ltrim(userid))) from audit
if that doesn't return the correct value then I would do a replace to remove the empty space:
select convert(int, replace(userid, char(0), '')) from audit
This is how I solved the problem in my case:
First of all I made sure the column I need to convert to integer doesn't contain any spaces:
update data set col1 = TRIM(col1)
I also checked whether the column only contains numeric digits.
You can check it by:
select * from data where col1 like '%[^0-9]%' order by col1
If any nonnumeric values are present, you can save them to another table and remove them from the table you are working on.
select * into nonnumeric_data from data where col1 like '%[^0-9]%'
delete from data where col1 like '%[^0-9]%'
Problems with my data were the cases above. So after fixing them, I created a bigint variable and set the values of the varchar column to the integer column I created.
alter table data add int_col1 bigint
update data set int_col1 = CAST(col1 AS VARCHAR)
This worked for me, hope you find it useful as well.

How to add column dynamically in where clause

I want to include column in where clause depending on the condition.
e.g
select * From emp
where id=7,
and if(code is not null) then code=8;
how can i do this in sql server
If I understand you correct, you could make use of COALESCE.
COALESCE()
Returns the first nonnull expression
among its arguments.
SQL Statement
SELECT *
FROM emp
WHERE id=7
AND code = COALESCE(#code, code)
If code is a column rather than a variable the query in your question would be rewritten as follows.
SELECT *
FROM emp
WHERE id=7 AND (code IS NULL OR code=8)
You'll probably have to create a query dynamically, as a string, and then use the Execute method to actually execute it. This approach has some potentially optimization issues, but it's commonly done. You might wan to Google T-SQL Dynamic Query, or something like that.
Also use this in case of Null value in #var1.
Select * from ABC where Column1 = isNull(#var1, Column1)
here is the example:
declare #SQL varchar(500)
declare #var1 int
set int = 1
set #SQL = 'Select * from ABC Where 1 = 1'
if(#var1 = 1)
set #SQL + #SQL ' And column1 = ' #var1
exec(#SQL)
You can use COALESCE function.
Well,
I don't know if i understood your question, but i guess that you want to include the value of the code column in the results.
If i'm right it can be done in the select part instead of the where clause. i. e.
Select ..., case when code is not null then 8 else code end as code from emp where id = 7
The other interpretation is that you want to filter rows where code <> 8,that would be
Select * from emp where id = 7 and (code is null OR code = 8)

Using variable in SQL LIKE statement

I've got a sproc (MSSQL 2k5) that will take a variable for a LIKE claus like so:
DECLARE #SearchLetter2 char(1)
SET #SearchLetter = 't'
SET #SearchLetter2 = #SearchLetter + '%'
SELECT *
FROM BrandNames
WHERE [Name] LIKE #SearchLetter2 and IsVisible = 1
--WHERE [Name] LIKE 't%' and IsVisible = 1
ORDER BY [Name]
Unfortunately, the line currently running throws a syntax error, while the commented where clause runs just fine. Can anyone help me get the un-commented line working?
If you are using a Stored Procedure:
ALTER PROCEDURE <Name>
(
#PartialName VARCHAR(50) = NULL
)
SELECT Name
FROM <table>
WHERE Name LIKE '%' + #PartialName + '%'
Joel is it that #SearchLetter hasn't been declared yet? Also the length of #SearchLetter2 isn't long enough for 't%'. Try a varchar of a longer length.
As Andrew Brower says, but adding a trim
ALTER PROCEDURE <Name>
(
#PartialName VARCHAR(50) = NULL
)
SELECT Name
FROM <table>
WHERE Name LIKE '%' + LTRIM(RTRIM(#PartialName)) + '%'
But in my opinion one important thing.
The "char(number)" it's lenght of variable.
If we've got table with "Names" like for example [Test1..Test200] and we declare char(5) in SELECT like:
DECLARE #variable char(5)
SET #variable = 'Test1%'
SELECT * FROM table WHERE Name like #variable
the result will be only - "Test1"! (char(5) - 5 chars in lenght; Test11 is 6 )
The rest of potential interested data like [Test11..Test200] will not be returned in the result.
It's ok if we want to limit the SELECT by this way.
But if it's not intentional way of doing it could return incorrect results from planned
( Like "all Names begining with Test1..." ).
In my opinion if we don't know the precise lenght of a SELECTed value, a better solution could be something like this one:
DECLARE #variable varchar(max)
SET #variable = 'Test1%'
SELECT * FROM <table> WHERE variable1 like #variable
This returns (Test1 but also Test11..Test19 and Test100..Test199).
This works for me on the Northwind sample DB, note that SearchLetter has 2 characters to it and SearchLetter also has to be declared for this to run:
declare #SearchLetter2 char(2)
declare #SearchLetter char(1)
Set #SearchLetter = 'A'
Set #SearchLetter2 = #SearchLetter+'%'
select * from Customers where ContactName like #SearchLetter2 and Region='WY'
DECLARE #SearchLetter2 char(1)
Set this to a longer char.
We can write directly too...
DECLARE #SearchLetter CHAR(1)
SET #SearchLetter = 'A'
SELECT *
FROM CUSTOMERS
WHERE CONTACTNAME LIKE #SearchLetter + '%'
AND REGION = 'WY'
or the following way as well if we have to append all the search characters then,
DECLARE #SearchLetter CHAR(1)
SET #SearchLetter = 'A' + '%'
SELECT *
FROM CUSTOMERS
WHERE CONTACTNAME LIKE #SearchLetter
AND REGION = 'WY'
Both these will work
I had also problem using local variables in LIKE.
Important is to know: how long is variable.
Below, ORDER_NO is 50 characters long, so You can not use: LIKE #ORDER_NO, because in the end will be spaces.
You need to trim right side of the variable first.
Like this:
DECLARE #ORDER_NO char(50)
SELECT #ORDER_NO = 'OR/201910/0012%'
SELECT * FROM orders WHERE ord_no LIKE RTRIM(#ORDER_NO)
It may be as simple as LIKE '%%[%3]%%' being [%3] the input variable.
This works for me with SAP B1 9.1
I ran into a similar problem. I needed to use just a small piece of a URL saved in my database where the front and ends were irrelevant.
I first attempted to use:
DECLARE #variable VARCHAR(250) = %x%;
SELECT * FROM tblone WHERE column1 LIKE '#variable'
However, this returned the error:
Arithmetic overflow error converting numeric to data type varchar
My working query was formatted:
DECLARE #variable VARCHAR(1000) = x;
SELECT * FROM tblone WHERE column1 LIKE '%'+#variable+'%'

Resources