How can I store the result of exec in a variable? The output is JSON.
My SQL query is complex and dynamically generated, so I have to set a variable and execute it.
create PROCEDURE dbo.RetrievePerfCounterData #jsonOutput NVARCHAR(MAX) OUTPUT
AS
BEGIN
declare #sql NVARCHAR(MAX)
SET #sql = ' SELECT TOP (1) getdate() AS ''dateTime'' ,suser_sname()AS ''user'' FOR JSON PATH '
exec (#sql)
END
Here's my attempt at storing the data in a variable:
DECLARE #json AS NVARCHAR(MAX)
EXEC dbo.RetrievePerfCounterData #jsonOutput = #json OUTPUT
DECLARE #myVar VARCHAR(MAX)
DECLARE #SQL NVARCHAR(MAX)
IF OBJECT_ID('tempdb..#t1') IS NOT NULL DROP TABLE #t1
CREATE TABLE #t1 (col1 INT, col2 INT)
INSERT INTO #t1
SELECT 1, 1
UNION
SELECT 1, 2
SET #SQL = 'SET #myVar = (SELECT * FROM #t1 AS T FOR JSON AUTO);'
EXEC sp_executesql #SQL, N'#myVar VARCHAR(MAX) OUT', #myVar OUT
SELECT #myVar
You need to use a subquery:
SET #json = (SELECT TOP (1) getdate() AS [dateTime],suser_sname()AS [user] FOR JSON PATH);
Related
I am trying to update records and insert their audits to audit table.
For this purpose stored procedure waiting for above variables.
#m_obj_id INT,
#m_obj_code NVARCHAR(250),
#m_f_code NVARCHAR(250),
#m_nv NVARCHAR(4000),
#m_last_mod_by INTEGER,
#table_name SYSNAME,
--#where_clause NVARCHAR(4000)
Stored procedure formatting these variables as;
UPDATE #table_name SET #m_f_code=#m_nv WHERE id=#m_obj_id
And at last part inserting into audit.
I can use it with doing SELECT CONCAT and copying all the rows then execute.
But my goal is here not expecting #m_obj_id from user and replace it #where_clause. And use this #where_clause to get ids inside.
So far I tried;
DECLARE #Sql NVARCHAR(MAX)
DECLARE #RecordId int = 0
BEGIN
SET #SQL = N'
SELECT #RecordId = MIN(id)
FROM ' + #table_name + '
WHERE id > #RecordId AND (' + #where_clause + ')
IF #RecordId IS NULL BREAK
SET #m_obj_id = #RecordId'
Exec sp_executesql #sql
But couldnt get far with it.
Then I tried something like;
DECLARE #RowsToProcess int
DECLARE #CurrentRow int
DECLARE #SelectCol1 int
DECLARE #sql NVARCHAR(MAX)
SET #sql = N'
DECLARE #table1 TABLE (RowID int not null primary key identity(1,1), col1 int )
INSERT into #table1 (col1) SELECT id FROM ' + #table_name + ' Where ' + #where_clause + '
SET #RowsToProcess=##ROWCOUNT'
EXEC sp_executesql #sql,
N'#RowsToProcess INT OUTPUT', #RowsToProcess OUTPUT
SET #CurrentRow=0
WHILE #CurrentRow<#RowsToProcess
BEGIN
SET #CurrentRow=#CurrentRow+1
DECLARE #sql2 NVARCHAR(MAX)
SET #sql2 = N'
SET #m_obj_id =
(SELECT col1
FROM #table1
WHERE RowID=#CurrentRow)'
EXEC sp_executesql #sql2
But still no luck.
Can I achieve this any how? I am trying to do this for more than it should be.
Thanks all.
The non-dynamic way to implement dynamic filtering on sql is the following:
where id=#m_obj_id or #m_obj_id is null
For a LOT of more details on how to choose between dynamic and non-dynamic sql on this, I recommend this article by Erland Sommarskog
I found a solution. Thanks everyone for responding.
I used a temp table like
DECLARE #RowsToProcess INTEGER
DECLARE #CurrentRow INTEGER
DECLARE #SelectCol1 INTEGER
CREATE TABLE #tmp (RowID INTEGER NOT NULL PRIMARY KEY IDENTITY(1,1), col1 int)
DECLARE #sql NVARCHAR(MAX)
SET #sql = N'
INSERT into #tmp (col1) SELECT id FROM ' + #table_name + ' Where ' + #where_clause + '
SET #RowsToProcess=##ROWCOUNT'
INSERT INTO #tmp
EXEC sp_executesql #sql,
N'#RowsToProcess INT OUTPUT', #RowsToProcess OUTPUT
SET #CurrentRow=0
WHILE #CurrentRow<#RowsToProcess
BEGIN
SET #CurrentRow=#CurrentRow+1
SET #m_obj_id =
(SELECT col1
FROM #tmp
WHERE RowID=#CurrentRow)
Do stuff....
I'm using a while loop to iterate through some tables and carry out a replace on a field, to remove all the hyphens. All of the fields are varchar.
DECLARE #Table TABLE (TableName VARCHAR(max),Id int identity(1,1))
INSERT INTO #Table
Select distinct table_name From INFORMATION_SCHEMA.COLUMNS
DECLARE #max int
DECLARE #SQL VARCHAR(max)
DECLARE #TableName VARCHAR(max)
DECLARE #id int = 1
select #max = MAX(Id) from #Table
WHILE (#id <= #max)
BEGIN
SELECT #TableName = TableName FROM #Table WHERE Id = #id
SET #SQL = 'update '+ #TableName +' set colA = replace(colA,'-','');'
EXEC(#SQL)
SET #id = #id +1
END
the error I receive is:
The data types varchar(max) and varchar are incompatible in the subtract operator.
I've tried changing the varchar variables to fixed lengths or all to max, but nothing seems to work.
You need to use two single quotes when creating a single quote inside of a string:
DECLARE #Table TABLE (TableName VARCHAR(max),Id int identity(1,1))
INSERT INTO #Table
Select distinct table_name From INFORMATION_SCHEMA.COLUMNS
DECLARE #max int
DECLARE #SQL VARCHAR(max)
DECLARE #TableName VARCHAR(max)
DECLARE #id int = 1
select #max = MAX(Id) from #Table
WHILE (#id <= #max)
BEGIN
SELECT #TableName = TableName FROM #Table WHERE Id = #id
SET #SQL = 'update '+ #TableName +' set colA = replace(colA,''-'','''');'
EXEC(#SQL)
SET #id = #id +1
END
I have a list of columns that are dynamic then select the column in table that are in the list.
For example
Select (List of columns)
from tablename
Here is my code
SET NOCOUNT ON;
DECLARE #table TABLE(cols varchar(50));
DECLARE #tablename NVARCHAR(255);
DECLARE #tableid INT;
DECLARE #sSQL NVARCHAR(500);
SET #tableid = (SELECT DISTINCT TABLEID FROM faciltyShowedDetails WHERE layerid = #layerid);
SET #tablename = (SELECT dbo.FNC_Search_GetSearchTable(#tableid))
INSERT INTO #table(cols)
SELECT COLUMN_NAME
FROM faciltyShowedDetails
WHERE layerid = #layerid;
I want to select from the list of column in #table.
You would construct the query and use dynamic SQL. Assuming the "list" is really a comma-delimited list:
declare #sql nvarchar(max);
set #sql = 'select [cols] from tablename';
set #sql = replace(#sql, '[cols]', #cols);
exec sp_executesql #sql;
EDIT:
To get the columns from a table, you can use the trick:
declare #cols varchar(max);
select #cols = ', ' + columnname
from #table t;
You then have to remove the first comma (using stuff()) in the previous code.
I declared a variable #Obj and assign a complete table name 'ODS..Account' to it.
DECLARE #Obj VARCHAR(255)
Then I used it in a query immediately after FROM Clause. I perceive it is just a string, unable to act as a table object. So how can I fix the code to get it works? Cheers
INSERT Control.dbo.Consistency_Check
(Table_Name
,Schema_Name
,Id
,Incremental_DateTime_Column
)
SELECT
#Tab
,'ODS'
,Id
,SystemModstamp
FROM
#Obj )
You can use a local variable as a scalar value, not as a function. To do this, you need dynamic SQL:
declare #sql varchar(max);
select #sql = '
INSERT Control.dbo.Consistency_Check(Table_Name, Schema_Name, Id, Incremental_DateTime_Column)
SELECT ''#Tab'', 'ODS', Id, SystemModstamp
FROM #Tab
';
select #sql = replace(#sql, '#tab', #tab);
exec sp_executesql #sql;
Slightly different way of doing it with dynamic SQL:
DECLARE #Obj VARCHAR(255) = 'dbo.table'
DECLARE #SQL NVARCHAR(MAX) = ''
SET #SQL = #SQL +
'INSERT Control.dbo.Consistency_Check
(Table_Name
,Schema_Name
,Id
,Incremental_DateTime_Column
)
SELECT
#Tab
,''ODS''
,Id
,SystemModstamp
FROM
' + #Obj + ''
EXEC (#SQL)
You cannot. You probably want to use dynamic query. i.e. workout the SQL query string into a variable and exec using sp_executesql.
You may use the same variable name in the dynamic SQL but I changed it to #p_Tab for the example.
DECLARE #Tab int = 3
DECLARE #SQLString nvarchar(500)
DECLARE #ParmDefinition nvarchar(500) = N'#p_Tab int';
Declare #TableName nvarchar(100) = 'ODS..Account'
/* Build the SQL string dynamicly.*/
SET #SQLString = N'INSERT Control.dbo.Consistency_Check
(Table_Name
,Schema_Name
,Id
,Incremental_DateTime_Column
)
SELECT
#p_Tab
,''ODS''
,Id
,SystemModstamp
FROM
'+ #TableName
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#p_Tab = #Tab
Further reference: https://msdn.microsoft.com/en-us/library/ms188001.aspx
tables:
create table TabA
(ID int, Name varchar(20))
insert into TabA
select 1,'ABC' union
select 2,'DEF' union
select 3,'GHD'
create table TabB
(ID int, Name varchar(20))
insert into TabA
select 1,'XYZ' union
select 2,'STF' union
select 3,'LDZ'
create table status
(Result1 int,Result2 int )
Create table query(query1 varchar(1000),query2 varchar(1000))
Insert into query(query1,query2)
select '''select COUNT(*) from TabA''','''select COUNT(* )from TabB'''
select * from query
procedure:
create Procedure [dbo].spStatus
AS
BEGIN
SET NOCOUNT ON;
Declare #sqlString1 nvarchar(1000)
,#sqlString2 nvarchar(1000)
,#col_value1 varchar(256)
,#col_value2 varchar(256)
select #sqlString1 = query1
, #sqlString2 =query2
from Query
EXEC sp_executesql
#query=#sqlString1, --sql string is your full select statement
#params = N'#col_Value1 varchar(256) OUTPUT',
#col_Value1 = #col_Value1 OUTPUT
print(#sqlString1)
-- #sqlString2, --sql string is your full select statement
--#params = N'#col_Value2 varchar(256) OUTPUT',
-- #col_Value2 = #col_Value2 OUTPUT
Insert Into dbo.Status(Result1,Result2 )
Values(#col_Value1,#col_Value2)
End
It works if we use #query=#sqlString1 only but I want both statement #query=#sqlString1,#query=#sqlString2 should execute together.
Please help how can we use both statement to execute?
Thanks in Advance
Did you mean:
SET #sqlString1 = #sqlString1 + ';' + #sqlString2;
EXEC sp_executesql #query = #sqlString1 --...
Concat the two queries together with a + (#query=#sqlString1 + '; ' + #sqlString2)
Then use two variables to capture the two counts into output variables
OR
Insert into query(query1,query2)
EXEC sp_executesql 'SELECT ( select COUNT(*) from TabA ) AS query1, ( select COUNT(*)from TabB ) AS query2'
... but really and truly dynamic SQL isn't needed for that at all.
try this:
--add this
DECLARE #SQL nvarchar(max)
SET #SQL=ISNULL(#sqlString1,'')+';'+ISNULL(#sqlString2,'')
--change this
EXEC sp_executesql #query=#SQL
,#params = N'#col_Value1 varchar(256) OUTPUT'
,#col_Value1 = #col_Value1 OUTPUT