Execute dynamic query only to get affected row count - sql

I want to execute a dynamic query to get the affected row count. But SQL Result pane returns me the result after executing it. How to avoid returning the columns. I tried the below way.
DECLARE #Command NVARCHAR(MAX)= 'SELECT * FROM Product WHERE ID = 12'
DECLARE #Count AS INT
EXEC sp_executesql #Command, N'#C INT OUTPUT', #C=#Count OUTPUT
IF (#Count > 0)
BEGIN
EXECUTE (#Command)
END
ELSE
BEGIN
DECLARE #CatalogProduct VARCHAR(MAX) = 'SELECT p.ManufactureCode,p.PartNo,p.Size,p.ID AS ProductID,p.Name ,p.ParentProductID,p.BasePrice FROM Product.Product p WHERE p.ThruDate > GETDATE() '+#Where
EXECUTE (#CatalogProduct)
END
END
I want to avoid returning the null column set from the above attached image.

You can turn off the display, but I think a better approach is to get the count you want directly:
DECLARE #Command NVARCHAR(MAX)= 'SELECT * FROM Product WHERE ID = 12';
DECLARE #count AS INT;
DECLARE #CntCommand NVARCHAR(MAX);
SET #CntCommand = 'SELECT #count = COUNT(*) FROM (' + #Command + ') x)';
EXEC sp_executesql #CntCommand, N'#count INT OUTPUT', #count=#count OUTPUT;

Why not simply?
IF (SELECT COUNT(*) FROM Product = 12) > 0 BEGIN...
I can't see why the COUNT statement needs to be dynamic; there's nothing dynamic about it.
Also, having the SQL '... WHERE p.ThruDate > GETDATE() '+#Where is a terrible idea. If #where is a parameter it'll be wide open to SQL injection.

Try this one. Returns number of rows affected by the last query:
select ##Rowcount

DECLARE #Command NVARCHAR(MAX)= 'SELECT * FROM Product WHERE ID = 12'
DECLARE #CountCommand NVARCHAR(MAX)= 'SELECT #Count=count(1) FROM Product WHERE ID = 12'
DECLARE #Count AS INT
EXEC sp_executesql #CountCommand , N'#Count INT OUTPUT', #Count=#Count OUTPUT
IF (#Count > 0)
BEGIN
EXECUTE (#Command)
END
ELSE
BEGIN
DECLARE #CatalogProduct VARCHAR(MAX) = 'SELECT p.ManufactureCode,p.PartNo,p.Size,p.ID AS ProductID,p.Name ,p.ParentProductID,p.BasePrice FROM Product.Product p WHERE p.ThruDate > GETDATE() '+#Where
EXECUTE (#CatalogProduct)
END
END

Related

Dynamic SQL output of a query to a variable

I would like to output the result of the dynamic SQL into a variable called #Count but not sure what the syntax or even the code should like to accomplish this.
The code looks as follows:
declare #tab nvarchar(255) = 'Person.person'
declare #Count int
declare #SQL nvarchar(max) = 'select count(*) from '+ #tab
exec(#SQl)
select #Count
thank you
Here's another way to do it that also safely addresses the SQL Injection isuues:
/* Counts the number of rows from any non-system Table, *SAFELY* */
-- The table name passed
DECLARE #PassedTableName as NVarchar(255) = 'Person.Person';
-- Make sure this isn't a SQL Injection attempt
DECLARE #ActualTableName AS NVarchar(255)
SELECT #ActualTableName = TABLE_SCHEMA + '.' + TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = PARSENAME(#PassedTableName,1)
AND TABLE_SCHEMA = PARSENAME(#PassedTableName,2)
-- make a temp table to hold the results
CREATE TABLE #tmp( cnt INT );
-- create the dynamic SQL
DECLARE #sql AS NVARCHAR(MAX)
SELECT #sql = 'SELECT COUNT(*) FROM ' + #ActualTableName + ';'
-- execute it and store the output into the temp table
INSERT INTO #tmp( cnt )
EXEC(#SQL);
-- Now, finally, we can get it into a local variable
DECLARE #result AS INT;
SELECT #result = cnt FROM #tmp;
You can utilize sp_executesql to execute your count() query, and output it #Count.
Try this:
-- Set the table to count from
declare #tab nvarchar(255) = 'Person.person'
-- Assign the SQL query
declare #SQL nvarchar(255) = N'SELECT count(*) FROM ' + #tab
-- Pepare for sp_executesql
declare #Count int
declare #Params nvarchar(100) = N'#Count int output'
-- Set the count to #Count
exec sp_executesql #SQL, #Params, #Count=#Count output
-- Output #Count
select #Count
One last thing: Person.person looks like you might be trying to reference a person column from a Person table. But the above query is a literal representation of what it looks like you're trying to achieve in your question.
The below question is pretty much identical to what you are asking here.
sp_executeSql with output parameter
DECLARE #retval int
DECLARE #sSQL nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #tablename nvarchar(50)
SELECT #tablename = N'products'
SELECT #sSQL = N'SELECT #retvalOUT = MAX(ID) FROM ' + #tablename;
SET #ParmDefinition = N'#retvalOUT int OUTPUT';
EXEC sp_executesql #sSQL, #ParmDefinition, #retvalOUT=#retval OUTPUT;
SELECT #retval;

How to Set a variable using OPENQUERY in SQL Server

I am trying to read data from a table. This table have a list of table name.
for each row of the data set I want to run a couple of queries to pull data and insert it into a temporary table.
Here is What I have done
DECLARE #campName varchar(255);
DECLARE #sqlCommand varchar(1000);
DECLARE #sqlCommandMySQL varchar(1000);
DECLARE #LastRun varchar(60);
DECLARE #OPENQUERY varchar(1000);
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT LTRIM(RTRIM(CallListName)) AS CallListName
FROM [SMSQL1].[RDI_System].[dbo].[Campaigns]
WHERE dialer_campaign = 1 AND i3Server ='I3New' AND ClientID = 111 AND (EndDate IS NULL OR EndDate >= getdate() - 7)
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO #campName
WHILE ##FETCH_STATUS = 0
BEGIN
--SET #LinkedServer = 'GUARDIAN';
SET #OPENQUERY = 'SELECT #LastRun = lr FROM OPENQUERY(GUARDIAN,''';
SET #sqlCommandMySQL = 'SELECT IFNULL(MAX(lastRun), DATE_SUB(NOW(), INTERVAL 7 DAY) ) AS lr
FROM guardian_dynamo.runtimes_i3
WHERE CampaignListName = "'+#campName+'" '')';
print #OPENQUERY + #sqlCommandMySQL;
EXEC(#OPENQUERY + #sqlCommandMySQL);
SET #sqlCommand = ' INSERT INTO #finalList(Attemtps, CAMPAIGNNAME, FINISHCODE, CALLDATE, AGENTID, RDINotes, PHONE, MERCHANTAccount)
SELECT ATTEMPTS, CAMPAIGNNAME, FINISHCODE, CALLDATE, AGENTID, RDINotes, PHONE, MERCHANTAccount
FROM [I3_IC4].[dbo].['+ #campName +']
WHERE CALLDATE > '''+#LastRun+''' AND ISNULL(status, ''C'') IN (''U'', ''E'', ''A'', ''F'') ';
EXEC (#sqlCommand);
FETCH NEXT FROM MY_CURSOR INTO #campName
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR;
every time I run this query I get this error
Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "#LastRun".
I am not sure why since I am declaring this variable on the top as you can see in my code above.
the took the output of print #OPENQUERY + #sqlCommandMySQL; and executed that manually. It worked with no issue and the variable #LastRun will have a datetime value as it should.
You need to use sp_executesql to execute the dynamic query which helps you output the variable(#LastRun)
Declare #OPENQUERY Nvarchar(max), #sqlCommandMySQL Nvarchar(max), #OPENQUERYFINAL Nvarchar(max)
....
SET #OPENQUERY = 'SELECT #LastRun = lr FROM OPENQUERY(GUARDIAN,''';
SET #sqlCommandMySQL = 'SELECT IFNULL(MAX(lastRun), DATE_SUB(NOW(), INTERVAL 7 DAY) ) AS lr
FROM guardian_dynamo.runtimes_i3
WHERE CampaignListName = "'+#campName+'" '')';
--print #OPENQUERY + #sqlCommandMySQL;
SET #OPENQUERYFINAL = #OPENQUERY + #sqlCommandMySQL;
EXEC sp_executesql #OPENQUERYFINAL,
N'#LastRun varchar(10) OUTPUT',
#LastRun output
Demo
DECLARE #str VARCHAR(10),
#sql NVARCHAR(max)
SET #sql= 'select #str=1 '
EXEC Sp_executesql
#sql,
N'#str varchar(10) OUTPUT',
#str output
PRINT #str

SQL "if exists..." dynamic query

Suppose I have a query stored in a variable like this (it's actually dynamically populated and more complex, but this is for demonstration purposes):
DECLARE #Query VARCHAR(1000) = 'SELECT * FROM dbo.MyTable'
Is there a way to check if the query would return any results? Something like this, but this doesn't work:
IF EXISTS (#Query)
BEGIN
-- do something
END
The only way that I can think of to do this is to put the results in a temp table and then query from that, but that is not ideal because the columns in the dynamic query can vary and I really don't need the temp table at all for any reason other than checking whether some rows would be returned. Is there a better way?
Try Executing the Dynamic query and use ##RowCount to find the existence of rows.
DECLARE #Query NVARCHAR(1000) = 'SELECT * FROM [dbo].[Mytable]',
#rowcnt INT
EXEC Sp_executesql #query
SELECT #rowcnt = ##ROWCOUNT
IF #rowcnt > 0
BEGIN
PRINT 'row present'
END
Try this:
DECLARE #Query NVARCHAR(1000) = 'SELECT #C = COUNT(*) FROM dbo.MyTable'
DECLARE #Count AS INT
EXEC sp_executesql #Query, N'#C INT OUTPUT', #C=#Count OUTPUT
IF (#Count > 0)
BEGIN
END
I know this answer is too late. but, I'm leaving this here to help someone else to use IF EXISTS with a dynamic query.
This is how you should do it with dynamic queries.
DECLARE #Query VARCHAR(MAX)
SET #Query = 'SELECT * FROM [dbo].[MyTable]'
SET #Query = 'IF EXISTS (' + #Query + ')
BEGIN
-- do something
print ''1''
END
ELSE
BEGIN
-- do something else
print ''0''
END
'
exec (#Query)
Hope this helped someone. Vote if it did :)
You can use EXEC to execute sql statement, then call ##ROWCOUNT which Returns the number of rows affected by the last statement, to check row exists in sql select stetement.
DECLARE #Query VARCHAR(1000) = 'SELECT * FROM dbo.MyTable',#hasRow int
EXEC (#Query)
SELECT #hasRow =##ROWCOUNT // Returns the number of rows affected by the last statement
PRINT #hasRow
IF #hasRow > 0
BEGIN
Print 1
END
BEGIN
Print 2
END
Hi I think that only way is to put IF EXISTS part into code of execution. My case is to stop execution in point when select affects at least one row, that is goal of IF EXISTS.
Little example that saves reading all records covering by condition to first occurence:
set nocount off;
drop table if exists #temp
go
create table #temp (idCol int identity(1,1),someText nvarchar(1))
go
insert into #temp values ('a')
go 25000
declare #query nvarchar(max)
,#resultFork bit
set #query = 'if exists (select * from #temp where idCol % 3 = 0)
set #resultFork=1
else
set #resultFork=0'
print #query
exec sp_executeSQL #query, N'#resultFork int output', #resultFork=#resultFork output
print #resultFork
/*Now U can use #resultFork in simple if condition...
if #resultFork = 1
begin
--
end
else
begin
--
end
*/

Build select statement dynamically and use it to populate a stored procedure variable

I am trying to get count of a rows with specific values in a table, and if the count is 0, then add a value in the table. This count is a local variable in stored procedure.
I am building the SQL dynamically and storing SQL statement into a nvarchar variable.
Then, using EXEC I am running this SQL as follows hoping to populate count variable.
But it's not working.
DECLARE #qry NVARCHAR(max)
DECLARE #count INT
-- building #qry will result as follows
#qry = SELECT #count = COUNT(*) FROM aTable WHERE (col1 = #col1 AND ...)
#count = EXEC #qry
IF #count = 0
BEGIN
-- carry on with adding
END
In your sql ,why you are execute your query through EXEC because of your required output is already in #count variable so it is not need in your case.
Please refer below syntax.
DECLARE #qry Numeric
DECLARE #count INT
-- building #qry will result as follows
SELECT #count = COUNT(*) FROM aTable WHERE (col1 = #col1 AND ...)
IF #count = 0
BEGIN
-- carry on with adding
END
If you are building the query dynamically, you need sp_executesql. Try something like
-- building #qry will result as follows
#qry = 'SELECT #count = COUNT(*) FROM aTable WHERE (col1 = #col1 AND ...)'
EXEC sp_executesql #qry, N'#count INT OUTPUT', #count OUTPUT;
--Do whatever you want with #count...
Source: Aaron Bertrand's answer here and sp_executesql explanation..
I think #qry needs to be a string for executing, not the result of the select, like so:
DECLARE #qry NVARCHAR(max);
DECLARE #count INT;
-- building #qry will result as follows
SET #qry = 'SELECT COUNT(*) FROM aTable WHERE (col1 = #col1 AND ...)';
SET #count = exec #qry;

Assign db query value to t-sql variable in dynamic query

I have this requirement to be implemented in a stored procedure. Dynamically query the database to get the count of a table, store it in a t-sql variable and then take some decisions based on that.
This is the stored procedure that i am working on . This is throwing some errors as i don't think there is a simple way of assigning the result of a tsql dynamic query to a variable.
CREATE PROCEDURE test
AS
BEGIN
DECLARE #sql VARCHAR(255)
DECLARE #cnt int
SET #sql = 'SELECT COUNT(1) FROM myTable'
SET #cnt = EXEC(#sql)
IF (#cnt > 0)
PRINT 'A'
ELSE
PRINT 'B'
END
GO
Could someone tell me if there is a simpler way of achieving this using T-SQL ?
Thanks.
alternative:
declare #tablename varchar(512) = 'sometable'
declare #sql nvarchar(512) = 'set #count = (select count(*) from ' + #tablename + ')'
declare #count int
execute sp_executesql #sql, N'#count int output', #count=#count output
select case when #count > 0 then 'A' else 'B' end
Try this:
SET #sql = 'SELECT #cnt = COUNT(1) FROM myTable'
EXEC(#sql)