SQL Server - Compare int values in a select clause - sql-server

This is what I thought would be a simple select clause, however the following is giving me grief! I am using SQL Server 2008.
Basically I want to compare two integer values and return the boolean result in the select clause. Here is a simple example:
DECLARE #A INT
DECLARE #B INT
SET #A = 1
SET #B = 2
SELECT #A = #B
Currently the only output is "Command(s) completed successfully."
Where I reasonably believe it is assigning #A to #B.
I thought this would be simple but have not been able to achieve this.
Any help would be great! Thanks

try
SELECT CASE WHEN #A = #B THEN 1 ELSE 0 END
instead

Select Case When #A = #B Then 1 Else 0 End

Where I reasonably believe it is assigning #A to #B.
No... it is assigning B to A.
You need this:
SELECT case when #A - #B = 0 then 1 else 0 end

Related

generate row number by using variable in mssql

In MYSQL, I could use variable to generate the row number like below:
SET #num=0;
SELECT #num:=#num+1 rownum,id FROM test;
How should I do this in MSSQL? I tried below code:
DECLARE #num int
SET #num=0;
SELECT #num=#num+1 ,id FROM test;
then I got the error message:
A SELECT statement that assigns a value to a variable must not be
combined with data-retrieval operations.
I know there're some built-in functions in mssql to generate the row number, but I'd like to know how to use variables in this case to solve the issue.
Appreciate if someone could help on this. :)
As the error message says, you can't do variable assignment in a select statement that also does data retrieval.
You can assign a variable using a select statement...
declare #myInt int;
select #myvariable = 1; -- works just like "set" in this case
And you can do data retrieval...
select someColumn from MyTable
But not both at the same time.
You can assign a value to a variable when selecting from a table, as long as you don't also select columns that don't get assigned to variables.
declare #myInt int;
select #myInt = myIntColumn from MyTable
If MyTable has a lot of rows in it, it's not clear which row will be used to populate the value of #myInt. SQL is "allowed" to pick any row it wants.
Of course, in your case that doesn't matter, since you're assigning a literal value to the variable. You can do this, where by "can", I mean the syntax won't be rejected:
declare #myInt int = 0;
select #myInt = #myInt + 1
from MyTable
But don't do this. It's an interesting quirk, which I am showing it to you with the good faith assumption that you won't use it. It is not supported and should not be relied upon.
Jeff Moden wrote an article about this where he goes over the dangers.
But don't do it even if you follow his rules.
If you want to create a rownum based on the variable value, you can do that by updating the value in the table like below:
drop table if exists #t
create table #t (id int, rownum int)
insert #t(id) select 100
insert #t(id) select 200
insert #t(id) select 300
insert #t(id) select 400
declare #i int
set #i = 0
update #t set rownum = #i, #i = #i + 1
select * from #t
order by rownum

How to set value of multiple variable in T-SQL?

How to set value of multiple variable in SQL Server 2008. Like
Set #a = 10, #b = 'James'
Besides using SELECT #a = 10, #b = 'James', if you just want to set the values the first time they are declared, you can set the values of multiple variables when declaring them, as shown below:
DECLARE #a INT = 10, #b VARCHAR(10) = 'James' ;
Use SELECT instead of SET:
SELECT #a = 10, #b = 'James';
SELECT #a = 10, #b = 'James'
This should work, if the variables are properly declared.
Try like this,
Declare #a Int,#b Varchar(10)
select #a=10,#b='James'
As follows:
SET #a=10
SET #b='James'

T-SQL stored procedure - Detecting if a parameter is supplied as OUTPUT

Consider the following T-SQL code snippet:
CREATE PROC dbo.SquareNum(#i INT OUTPUT)
AS
BEGIN
SET #i = #i * #i
--SELECT #i
END
GO
DECLARE #a INT = 3, #b INT = 5
EXEC dbo.SquareNum #a OUTPUT
EXEC dbo.SquareNum #b
SELECT #a AS ASQUARE, #b AS BSQUARE
GO
DROP PROC dbo.SquareNum
The result set is:
ASQUARE BSQUARE
----------- -----------
9 5
As can be seen, #b is not squared, b/c it was not passed-in as output parameter (no OUTPUT qualifier when passing in the parameter).
I would like to know if there is a way I could check within stored procedure body (dbo.SquareNum body in this case) to see if a parameter has indeed been passed in as an OUTPUT parameter?
------ THIS WILL GIVE YOU THE BOTH VALUE IN squared------
CREATE PROC dbo.SquareNum(#i INT OUTPUT)
AS
BEGIN
SET #i = #i * #i
--SELECT #i
END
GO
DECLARE #a INT = 3, #b INT = 5
EXEC dbo.SquareNum #a OUTPUT
EXEC dbo.SquareNum #b OUTPUT
SELECT #a AS ASQUARE, #b AS BSQUARE
GO
DROP PROC dbo.SquareNum
-----TO CHECK STORED PROCEDURE BODY-----
SELECT OBJECT_NAME(object_id),
OBJECT_DEFINITION(object_id)
FROM sys.procedures
WHERE OBJECT_DEFINITION(object_id) =(SP_NAME)
Actually, there is a very simple way!
Make the parameter optional by setting a default value (#Qty AS Money = 0 Below)
Then, pass a value OTHER THAN THE DEFAULT when calling the procedure. Then immediately test the value and if it is other than the default value you know the variable has been passed.
Create Procedure MyProcedure(#PN AS NVarchar(50), #Rev AS NVarchar(5), #Qty AS Money = 0 OUTPUT) AS BEGIN
DECLARE #QtyPassed AS Bit = 0
IF #Qty <> 0 SET #QtyPassed = 1
Of course that means the variable cannot be used for anything other than OUTPUT unless you have a default value that you know will never be used as an INPUT value.
You can do this by query to sys views:
select
p.name as proc_name,
par.name as parameter_name,
par.is_output
from sys.procedures p
inner join sys.parameters par on par.object_id=p.object_id
where p.name = 'SquareNum'
or check in Management Studio in database tree:
[database] -> Programmability -> Stored Procedures -> [procedure] -> Parameters
Maybe I'm wrong but I don't believe it's possible. OUTPUT is part of the stored procedure definition so you should know when a parameter is or not OUTPUT. There is no way to set it dynamically so I think it's pointless to determine by code when a parameter is output or not because you already know it.
If you are trying to write a dynamic code, Piotr Lasota's answer should drive you to the correct way to realize when a parameter is Output.
Use the following query to get the name of all the parameters and to check if it is a output parameter:
select name, is_output from sys.parameters

SQL Server 2008: Finding a value from a string

This might be a very simple select statement, here's my question.
I have a variable
DECLARE #A varchar(128) --declaring variable
SET #A = 'sus_123456_R5_20140506' --setting value
I want to find the value after 'sus_' and before 'R5'
Also, the value in between is not of fixed length. So the function has to be dynamic.
However it always have sus and _R5_date. That's constant.
SET #A = 'sus_129_R5_20150408
Thanks
Use SUBSTRING in combination with CHARINDEX:
SELECT SUBSTRING(#A,CHARINDEX('sus_',#A,0)+4,CHARINDEX('_R5',#A,0)-5)
You can try this once using SUBSTRING() and CHARINDEX() FUNCTION
DECLARE #A varchar(128) --declaring variable
SET #A = 'sus_123456_R5_20140506'
select substring(#A,charindex('_',#A)+1,charindex('r5',#A)- (2+charindex('_',#A)))
Results in: 123456
(OR) This one using LEFT(),RIGHT() and CHARINDEX() function.
DECLARE #A varchar(128)
SET #A = 'sus_129_R5_20150408'
select right(left(#A,charindex('R5',#A) - 2),charindex('_',#A) - 1)
Results in: 129
Read more about String Function

select TOP (all)

declare #t int
set #t = 10
if (o = 'mmm') set #t = -1
select top(#t) * from table
What if I want generally it resulted with 10 rows, but rarely all of them.
I know I can do this through "SET ROWCOUNT". But is there some variable number, like -1, that causing TOP to result all elements.
The largest possible value that can be passed to TOP is 9223372036854775807 so you could just pass that.
Below I use the binary form for max signed bigint as it is easier to remember as long as you know the basic pattern and that bigint is 8 bytes.
declare #t bigint = case when some_condition then 10 else 0x7fffffffffffffff end;
select top(#t) *
From table
If you dont have an order by clause the top 10 will just be any 10 and optimisation dependant.
If you do have an order by clause to define the top 10 and an index to support it then the plan for the query above should be fine for either possible value.
If you don't have a supporting index and the plan shows a sort you should consider splitting into two queries.
im not sure I understand your question.
But if you sometimes want TOP and other times don't just use if / else construct:
if (condition)
'send TOP
SELECT TOP 10 Blah FROM...
else
SELECT blah1, blah2 FROM...
You can use dynamic SQL (but I, personally, try to avoid dynamic SQL), where you create a string of the statement you want to run from conditions or parameters.
There's also some good information here on how to do it without dynamic SQL:
https://web.archive.org/web/20150520123828/http://sqlserver2000.databases.aspfaq.com:80/how-do-i-use-a-variable-in-a-top-clause-in-sql-server.html
declare #top bigint = NULL
declare #top_max_value bigint = 9223372036854775807
if (#top IS NULL)
begin
set #top = #top_max_value
end
select top(#top) *
from [YourTableName]
a dynamic sql version isn't that's hard to do.
CREATE PROCEDURE [dbo].[VariableTopSelect]
-- Add the parameters for the stored procedure here
#t int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #sql nvarchar(max)
if (#t=10)
begin
set #sql='select top (10) * from table'
end
else
begin
set #sql='select * from table'
end
exec sp_executesql #sql
END
with this sp, if they send 10 to the sp, it'll select the top 10, otherwise it'll select all.
The best solution I've found is to select the needed columns with all of your conditions into a temporary table, then do your conditional top:
DECLARE #TempTable TABLE(cols...)
INSERT INTO #TempTable
SELECT blah FROM ...
if (condition)
SELECT TOP 10 * FROM #tempTable
else
SELECT * FROM #tempTable
This way you follow DRY, get your conditional TOP, and are just as easy to read.
Cheers.
It is also possible with a UNION and a parameter
SELECT DISTINCT TOP 10
Column1, Column2
FROM Table
WHERE #ShowAllResults = 0
UNION
SELECT DISTINCT
Column1, Column2
FROM Table
WHERE #ShowAllResults = 1
I might be too late now, or getting too old
But I solved that by using Top(100)Percent
This goes around all complexities
Select Top(100)Percent * from tablename;
Use the statement "SET ROWCOUNT #recordCount" at the beginning of the result query.The variable "#recordCount" can be any positive integer. It should be 0 to return all records.
that means , "SET ROWCOUNT 0" will return all records and "SET ROWCOUNT 15" will return only the TOP 15 rows of result set.
Drawback can be the Performance hit when dealing with large number of records. Also the SET ROWCOUNT will be effective throughout the scope of execution of the whole query.

Resources