Any way to optimize following query? - sql-server

Just a quick question, how can i optimize following my SQL server query and also, any way to replace while loop while loop?...Thanks
DECLARE #TOTAL INT, #COUNT INT=1, #ID INT,#FROMDATE DATE= '2016-11-01', #TODATE= '2016-11-10'
SELECT #TOTAL = COUNT(1)
FROM NUMBERS
WHILE #COUNT <= #TOTAL
BEGIN
SELECT #ID = ID
FROM #TEMP
WHERE ROW_ID = #COUNT
DECLARE #OUTPUT VARCHAR(MAX) = '';
EXEC SPSAMPLEPROC #ID, #FROMDATE, #TODATE, #OUTPUT OUTPUT;
SELECT #COUNT = #COUNT + 1;
END

Related

How put query with openquery faster?

this query takes a lot of time running.
Does anyone know anyway to put them faster?
DECLARE #actual as INT
DECLARE #expected as INT
DECLARE #ID as INT
DECLARE #TSQL varchar(100)
DECLARE #t table (c int)
DECLARE #Id_aux varchar(100)
SET #ID = (select max(id) from [STG].table where fk_country = 5 )
SET #Id_aux= CONVERT(NVARCHAR(100), #ID)
SET #TSQL = 'SELECT * FROM OPENQUERY([MA],''select count(*) from table where id <=' + #Id_aux + ''')'
INSERT INTO #t EXEC (#TSQL)
SET #expected = (select c from #t)
SET #actual = (SELECT count(*) from [STG].table where fk_country = 5 and id<=#ID)
select #expected
select #actual
Thanks
It is better to use a different approach while executing queries via linked servers.
EXECUTE ... AT [Linked_Server];
Benefits:
This way a query will be executed on the remote server. Guaranteed. Thus it will be much more performant.
Very easy to pass parameters. No strings concatenation.
Useful link: SQL Server: Execute At LinkedServer
Check it out below.
SQL
DECLARE #actual as INT;
DECLARE #expected as INT;
DECLARE #ID as INT;
DECLARE #TSQL varchar(100);
DECLARE #t table (c int);
--DECLARE #Id_aux varchar(100);
SET #ID = (select max(id) from [PAY_STG].pay.paybuddy_purchase_ex where fk_country = 5 );
--SET #Id_aux= CONVERT(NVARCHAR(100), #ID);
--SET #TSQL = 'SELECT *
-- FROM OPENQUERY([BE_PAY_MA],
-- ''SELECT COUNT(*) FROM paybuddy_purchase_ex WHERE id <=' + #Id_aux + ''')';
--INSERT INTO #t EXEC (#TSQL);
INSERT INTO #t
EXECUTE(N'SELECT COUNT(*) FROM paybuddy_purchase_ex WHERE id <= ?',
#ID) AT [BE_PAY_MA];
SET #expected = (select c from #t);
SET #actual = (SELECT count(*) from [PAY_STG].pay.paybuddy_purchase_ex where fk_country = 5 and id<=#ID);
select #expected;
select #actual;

updating Null Values in multiple columns of a table (SQL Server)

I have 64 columns and I am trying to automate the loop process. The loop runs but it shows 0 affected rows. If I update the table, column by column, it works.
Any idea why its showing 0 affected rows and what can be done ?
update temp set col1 = 'C' where col1 IS Null; -- works (276 rows affected)--
declare #count as int;
declare #name as varchar(max);
set #count = 2;
while #count < (SELECT Count(*) FROM INFORMATION_SCHEMA.Columns where TABLE_NAME = 'temp')+1
Begin
Set #name = (select name from (select colorder, name from (SELECT *
FROM syscolumns WHERE id=OBJECT_ID('temp')) colnames) as cl where colorder = #count)
Print #name
update temp set #name = 'C' where #name IS Null;
SET #count = #count + 1;
END;
You need to use dynamic sql to update the different columns during runtime as below.
Note: I just added/modified the dynamic sql part.
declare #count as int;
declare #name as varchar(max)
declare #sql nvarchar (1000)
set #count = 2
while #count < (SELECT Count(*) FROM INFORMATION_SCHEMA.Columns where TABLE_NAME = 'temp')+1
Begin
Set #name = (select name from (select colorder, name from (SELECT *
FROM syscolumns WHERE id=OBJECT_ID('temp')) colnames) as cl where colorder = #count)
Print #name
set #sql = N'update temp set ' + #name + '= ''C'' where ' + #name + ' is null ';
exec sp_executesql #sql
SET #count = #count + 1
END;

Dynamic sql to count rows in a table gives unexpected result

I get returned NULL when I execute this piece of code. Can you help me understand what is wrong with it? It's basically used to count rows in a table using a dynamic sql statement. Many thanks in advance.
DECLARE #sql nvarchar(4000),
#code nvarchar(40),
#count int,
#params nvarchar(4000)
SELECT #sql = N' SELECT #cnt = COUNT(*) FROM [Table1] WHERE [Column1]='''+quotename(#code)
SELECT #params = N'#code nvarchar(40), ' +
N'#cnt int OUTPUT'
EXEC sp_executesql #sql, #params, 'AD', #cnt = #count OUTPUT
SELECT #count as x
select #sql as y
Let me know please if you need additional details. Appreciate the pointers/help on this. PS. I have tested this manually and the count is more than 1.
It is a good practise to pass arguments (#code) as params to sp_executesql:
CREATE TABLE #Table1 (Column1 NVARCHAR(100));
INSERT INTO #Table1(Column1) VALUES ('AD'), ('AD');
DECLARE #sql NVARCHAR(MAX),
#code NVARCHAR(40),
#count INT,
#params NVARCHAR(4000);
SELECT #sql = N'SELECT #cnt = COUNT(*)
FROM #Table1
WHERE [Column1]= #code;'
,#params = N'#code NVARCHAR(40),
#cnt INT OUTPUT';
EXEC [dbo].[sp_executesql]
#sql
,#params
,#code = 'AD'
,#cnt = #count OUTPUT;
SELECT #count AS x;
LiveDemo

A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations

What is wrong with this statement?
ALTER Function [InvestmentReturn].[getSecurityMinLowForPeriod](#securityid int,
#start datetime,
#end datetime)
returns xml
begin
declare #results varchar(500)
declare #low int
declare #adjustedLow int
declare #day varchar(10)
if #end is null
begin
set #end = getdate()
end
set #adjustedLow = (select min(adjLow)
from (
select Low * [InvestmentReturn].[fn_getCorporateActionSplitFactor](isq.securityid, #start, convert(varchar,day, 111)) as adjLow
from
securityquote isq
where isq.securityid = #securityid and isq.day >= convert(varchar(10), #start, 111) and convert(varchar(10), #end, 111) >= isq.day
and low != -1
) as x)
select
top 1 #low = low
, #day = day
, #adjustedLow
--select high
from
securityquote sq
where
day >= convert(varchar(10), #start, 111) and convert(varchar(10), #end, 111) >= day
and securityid = #securityid and low != -1
order by low asc
set #results= '<results type="debug_min">'
set #results = #results + '<periodStart>' + coalesce(cast(#start as varchar(20)), 'NULL') + '</periodStart>'
set #results = #results + '<periodEnd>' + coalesce(cast(#end as varchar(20)), 'NULL') + '</periodEnd>'
set #results = #results + '<securityID>' + coalesce(cast(#securityID as varchar(10)), 'NULL') + '</securityID>'
set #results = #results + '<periodMin>' + coalesce(cast(#low as varchar(10)), '-11111') + '</periodMin>'
set #results = #results + '<coraxAdjustedPeriodMin>' + coalesce(cast(#adjustedLow as varchar(10)), '-11111') + '</coraxAdjustedPeriodMin>'
set #results = #results + '<dayMinOcurred>' + coalesce(#day, 'NULL') + '</dayMinOcurred>'
set #results = #results + '</results>'
return #results
Just to explain the answer (after getting where the error was caused), I simply removed #adjustedLow from the second select statement.
Column values from the SELECT statement are assigned into #low and #day local variables; the #adjustedLow value is not assigned into any variable and it causes the problem:
The problem is here:
select
top 1 #low = low
, #day = day
, #adjustedLow -- causes error!
--select high
from
securityquote sq
...
Detailed explanation and workaround: SQL Server Error Messages - Msg 141 - A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
You cannot use a select statement that assigns values to variables to also return data to the user
The below code will work fine, because i have declared 1 local variable and that variable is used in select statement.
Begin
DECLARE #name nvarchar(max)
select #name=PolicyHolderName from Table
select #name
END
The below code will throw error "A SELECT statement that assigns a value to a variable
must not be combined with data-retrieval operations" Because we are retriving data(PolicyHolderAddress) from table, but error says data-retrieval operation is not allowed when you use some local variable as part of select statement.
Begin
DECLARE #name nvarchar(max)
select
#name = PolicyHolderName,
PolicyHolderAddress
from Table
END
The the above code can be corrected like below,
Begin
DECLARE #name nvarchar(max)
DECLARE #address varchar(100)
select
#name = PolicyHolderName,
#address = PolicyHolderAddress
from Table
END
So either remove the data-retrieval operation or add extra local variable. This will resolve the error.
declare #cur cursor
declare #idx int
declare #Approval_No varchar(50)
declare #ReqNo varchar(100)
declare #M_Id varchar(100)
declare #Mail_ID varchar(100)
declare #temp table
(
val varchar(100)
)
declare #temp2 table
(
appno varchar(100),
mailid varchar(100),
userod varchar(100)
)
declare #slice varchar(8000)
declare #String varchar(100)
--set #String = '1200096,1200095,1200094,1200093,1200092,1200092'
set #String = '20131'
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(',',#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
--select #slice
insert into #temp values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
-- select distinct(val) from #temp
SET #cur = CURSOR FOR select distinct(val) from #temp
--open cursor
OPEN #cur
--fetchng id into variable
FETCH NEXT
FROM #cur into #Approval_No
--
--loop still the end
while ##FETCH_STATUS = 0
BEGIN
select distinct(Approval_Sr_No) as asd, #ReqNo=Approval_Sr_No,#M_Id=AM_ID,#Mail_ID=Mail_ID from WFMS_PRAO,WFMS_USERMASTER where WFMS_PRAO.AM_ID=WFMS_USERMASTER.User_ID
and Approval_Sr_No=#Approval_No
insert into #temp2 values(#ReqNo,#M_Id,#Mail_ID)
FETCH NEXT
FROM #cur into #Approval_No
end
--close cursor
CLOSE #cur
select * from #tem

how to assign the integer value to nvarchar or varchar datatype in stored procedure

how to assign the integer value to nvarchar or varchar datatype in stored procedure
DECLARE #SQLString nvarchar(max)
SET #SQLString = N'declare #Identifier int;
SELECT COUNT(*) FROM ' + #batch+' where Identifier = #Identifier'
i need to check whether the #SQLString is 0 or not.
i.e i want to check -----> if(#SQLString =0). how to assign a integer val to nvarchar or varchar
You could try something like
DECLARE #IntVal INT,
#ParamDef NVARCHAR(MAX),
#SQLString nvarchar(max),
#batch VARCHAR(MAX)
SELECT #batch = 'Batch',
#SQLString = N'SELECT #IntVal = COUNT(*) FROM ' + #batch,
#ParamDef = '#IntVal INT OUTPUT'
EXECUTE sp_executesql #SQLString,#ParamDef, #IntVal=#IntVal OUT
SELECT #IntVal
Have a look at sp_executesql (Transact-SQL)
I think this way is best:
DECLARE
#Cnt int,
#SQL nvarchar(max),
#batch sysname,
#Identifier varchar(30)
-- set #batch and #Identifier
SET #SQL = 'SELECT #Cnt = Count(*) FROM ' + #batch
+ ' WHERE Identifier = #Identifier'
EXEC sp_executesql #SQL, N'#Cnt int OUT, #Identifier varchar(30)',
#Cnt OUT, #Identifier
IF #Cnt = 0 BEGIN
--do something
END
ELSE BEGIN
--do something else
END
Though if you only care whether it's 0 or not, then you should do this instead, which can stop after finding only one row, instead of having to count them all:
DECLARE
#HasRows bit,
#SQL nvarchar(max),
#batch sysname,
#Identifier varchar(30)
-- set #batch and #Identifier
SET #SQL = 'SET #HasRows = CASE WHEN EXISTS (SELECT 1 FROM '
+ #batch + ' WHERE Identifier = #Identifier) THEN 1 ELSE 0 END'
EXEC sp_executesql #SQL, N'#HasRows bit OUT, #Identifier varchar(30)',
#HasRows OUT, #Identifier
IF #HasRows = 0 BEGIN
--do something
END
ELSE BEGIN
--do something else
END
However, if there's any way you can avoid using dynamic SQL and changing table names, that would be best. Then it is a simple query:
IF NOT EXISTS (SELECT 1 FROM TableName WHERE Identifier = #Identifier) BEGIN
-- do something
END
You're setting #SQLString to a query... if you want to see if it's '0', then you can just do:
IF #SQLString = '0'
But I think you're trying to find out if there are 0 rows in your batch, in which case, you mean something more like:
DECLARE #Res TABLE (cnt int);
INSERT #Res exec sp_executesql #SQLString;
IF (SELECT MAX(cnt) FROM #Res) = 0 /* Means empty batch */
convert it:
SET #var = CONVERT(VARCHAR, #intval)
Sascha
I am assuming that you are trying to check how many rows the dynamic sql returned you can do something like this:
DECLARE #SQLString nvarchar(max)
SET #SQLString = N'declare #Identifier int;
SELECT * FROM ' + #batch+' where Identifier = #Identifier'
exec #SQLString
set #SQLString = ##ROWCOUNT
if #SQLString = 0
begin
...
end

Resources