How do I query a value dynamically in T-SQL? - sql

For whatever reason, I can't seem to get a value out dynamically from SQL.
declare #SQL nvarchar(max)
declare #FieldName nvarchar(255)
declare #FieldValue nvarchar(max)
select #SQL = 'SELECT TOP 1 ' + #fieldname
+' FROM MyTable WHERE CM_CASE_YEAR = ' + LEFT(#ClaimNumber, 2)
+' AND CM_CASE_NUMBER = ' + RIGHT(#ClaimNumber, 6)
exec sp_executesql #sql, #FieldValue OUTPUT
select #FieldName + ' - ' + #FieldValue
When I run the #SQL query in another window, it displays one column with one value.
But, unfortunately when I try this, #FieldValue always comes back NULL.
Did I miss something the day they taught sp_executesql? Obviously! But what?

See this example
DECLARE #SQL NVARCHAR(MAX)
DECLARE #FieldName sysname = 'name'
DECLARE #FieldValue NVARCHAR(MAX)
SELECT #SQL = 'SELECT TOP 1
#FieldValue =' + QUOTENAME(#FieldName) + ' FROM sys.objects'
EXEC sp_executesql #SQL,
N'#FieldValue nvarchar(max) OUTPUT',
#FieldValue =#FieldValue OUTPUT
SELECT #FieldName + ' - ' + #FieldValue

sp_executesql returns (generates) a resultset. #FieldValue is meaningless in the code above - sp_executesql won't put any value into that variable.

Related

Variable in SQL query syntax

I want to make a simple SQL query like:
SELECT * FROM table WHERE $variable_2 = $variable_1
instead of a default one:
SELECT * FROM table WHERE column_name = $variable_1
It seems like first example doesn't work at all. Is it even possible to modify SQL query syntax in such way?
as this reference answer for:
in link:
Use Variable as SQL column Name in query
answer1:
declare #ColumnName varchar(50)
declare #sql nvarchar(max)
set #ColumnName = 'SalesData_' + convert(varchar(2),datepart(dd,getdate()))
set #sql = 'select ' + #ColumnName + ' from SalesTable'
print #sql
EXEC sp_sqlexec #sql
answer 2:
declare #ColumnName varchar(50)
declare #sql nvarchar(max)
set #ColumnName = 'SalesData_' + convert(varchar(2),datepart(dd,getdate()))
set #sql = 'select ' + #ColumnName + ' from yourschema.SalesTable'
print #sql

Select from list of tables / multiple tables with nested query - MS SQL

Not sure if this has an easy answer, but I'm basically trying to do this:
select id
from (select table_name from information_schema.columns where column_name = 'id')
where id = 1234
So passing in a list of tables into the FROM.
I'm trying to check all tables where this column exists if they have a matching value for 1234.
And without typing 31 times, select from table1, select from table2, etc etc
And without doing a bunch of joins.
possible?
I wrote this stored procedure.
It SUCKS I know, I've never written anything in tsql (teesquill?) before, and my goal was just to get something that works.
// find all occurrences of value in DB
USE [your db here]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[usp_query] (
#value NVARCHAR(128),
#colName NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #sql NVARCHAR(MAX);
-- DECLARE #tables NVARCHAR(MAX);
DECLARE #tabName NVARCHAR(MAX);
-- DECLARE #colName NVARCHAR(MAX);
DECLARE #count INT;
-- construct SQL
--SET #tables = N'SELECT Table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME LIKE "yourcollumn"'
DECLARE tabs CURSOR FOR SELECT table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME LIKE 'yourcollumn'
OPEN tabs
FETCH NEXT FROM tabs INTO #tabName
WHILE ##fetch_status = 0
BEGIN
--SET #count = N'SELECT count ( ' + #colName + ' ) FROM ' + #tabName + ' where ' + #colName + ' = ' + #value
DECLARE #SQLString NVARCHAR(500);
DECLARE #ParmDefinition NVARCHAR(500);
DECLARE #varOut NVARCHAR(25);
SET #SQLString = N'SELECT #count = count ( ' + #colName + ' ) FROM ' + #tabName + ' where ' + #colName + ' = ' + #value;
SET #ParmDefinition = N'#count NVARCHAR(25) OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#count = #varOut OUTPUT;
SET #sql = N'SELECT ' + #colName + ' FROM ' + #tabName + ' where yourcollumn = ' + #value;
IF #varOut > 0
SELECT #tabName AS 'value found in table'
--EXEC sp_executesql #sql
FETCH NEXT FROM tabs INTO #tabName
END
CLOSE tabs
END;

Invalid column name error when using QUOTENAME

I have several tables having the same structure. The tables are named by year that is 2001,2002 and so on. I am in need to search a column for a value in each table and get the count for each table.
I have created a stored procedure below but I keep getting an error
Invalid column 'lol'
This is the stored procedure used:
CREATE PROCEDURE [dbo].[CountSP]
#TableName NVARCHAR(128),
#SearchParam NVARCHAR(50),
#SearchInput NVARCHAR(200)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'SELECT COUNT('+QUOTENAME(#SearchParam)+') FROM ' + QUOTENAME(#TableName) +'WHERE'+QUOTENAME(#SearchParam)+'LIKE '+QUOTENAME(#SearchInput)+
+ N' SELECT * FROM '+QUOTENAME(#TableName)
EXECUTE sp_executesql #Sql
END
Executing it:
DECLARE #return_value INT
EXEC #return_value = [dbo].[CountSP]
#TableName = N'1999',
#SearchParam = N'USERDESC',
#SearchInput = N'lol'
SELECT 'Return Value' = #return_value
I don't know why you are using LIKE operator there while you don't use wildcards, also use SysName datatype directly for object names.
Create PROCEDURE [dbo].[CountSP]
(
#TableName SysName,
#SearchInput NVARCHAR(50),
#SearchParam SysName
)
AS
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX) = N'SELECT COUNT(' +
QUOTENAME(#SearchParam) +
N') FROM ' +
QUOTENAME(#TableName) +
N' WHERE ' +
QUOTENAME(#SearchParam) +
N' = ' + --You can change it to LIKE if needed
QUOTENAME(#SearchInput, '''') +
N';';
-- There is no benifits of using LIKE operator there
EXEC sp_executesql #SQL;
Then you can call it as
EXEC [dbo].[CountSP] N'YourTableNameHere', N'SearchInput', N'ColumnName';
This is because it is currently translated to :
SELECT COUNT([USERDESC]) FROM [1999] WHERE [USERDESC] LIKE [lol]
this means that it is comparing the "USERDESC" column with the "lol" column but from what I am understanding lol isn't a column but a value? which means you should lose the QUOTENAME for that variable.
See the documentation here : https://learn.microsoft.com/en-us/sql/t-sql/functions/quotename-transact-sql?view=sql-server-2017
You need to pass your parameter #SearchInput as a parameter to sp_execute:
CREATE PROCEDURE [dbo].[CountSP] #TableName sysname, --This is effectively the same datatype (as sysname is a synonym for nvarchar(128))
#SearchParam sysname, --Have changed this one though
#SearchInput nvarchar(200)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql nvarchar(MAX);
SET #Sql = N'SELECT COUNT(' + QUOTENAME(#SearchParam) + N') FROM ' + QUOTENAME(#TableName) + N'WHERE' + QUOTENAME(#SearchParam) + N' LIKE #SearchInput;' + NCHAR(13) + NCHAR(10) +
N'SELECT * FROM ' + QUOTENAME(#TableName);
EXECUTE sp_executesql #SQL, N'#SearchInput nvarchar(200)', #SearchInput;
END;
QUOTENAME, by default, will quote a value in brackets ([]). It does accept a second parameter which can be used to define a different character (for example QUOTENAME(#Value,'()') will wrap the value in parentheses). For what you want though, you want to parametrise the value, not inject (a quoted) value.

Dynamic SQL Output variable

Please see the SQL code below:
declare #Classification as varchar(5)
set #Classification =''
declare #ClassificationSQL as nvarchar(4000)
set #ClassificationSQL=''
declare #cnt int
declare #counts int
DECLARE NicheDeletionOffenderCursor CURSOR FOR
select classification from dbnicheoffenderclassificationlookup
Open NicheDeletionOffenderCursor
FETCH NEXT FROM NicheDeletionOffenderCursor INTO #Classification
WHILE ##FETCH_STATUS = 0
BEGIN
If #ClassificationSQL=''
set #ClassificationSQL='classification like ' + char(39) + '%' + #Classification + '%' + char(39)
else
set #ClassificationSQL=#ClassificationSQL + ' OR classification like ' + char(39) + '%' + #Classification + '%' + char(39)
FETCH NEXT FROM NicheDeletionOffenderCursor INTO #Classification
END
CLOSE NicheDeletionOffenderCursor
DEALLOCATE NicheDeletionOffenderCursor
SET #ClassificationSQL = 'select count(*) as cnt from person where id=903 and (' + #ClassificationSQL + ')'
EXECUTE sp_executesql #ClassificationSQL, N'#cnt int OUTPUT', #cnt=#Counts OUTPUT
How do I assign the count output from #ClassificationSQL to a variable to use in the next part of the TSQL?
There are several things to mention here:
No need to declare the variable used inside of the dynamic sql (i.e. #cnt) outside of it (i.e. at the top)
No need for a cursor as a simple SELECT #var = #var + column construct will concatenate
With no cursor, there is no need to declare the variable used with it (i.e. #Classification)
Single-quotes can be escaped by using two of them (i.e. ''). However, it could simply be preference to use CHAR(39) instead as some people find it to be more readable.
Setting a variable in dynamic SQL is just like regular SQL (i.e. SELECT #var = expression FROM...)
End result:
DECLARE #ClassificationSQL NVARCHAR(4000)
DECLARE #Counts INT
SET #ClassificationSQL = COALESCE(#ClassificationSQL + N' OR ', '')
+ N'classification LIKE ''%'
+ classification
+ N'%'''
FROM dbnicheoffenderclassificationlookup
SET #ClassificationSQL =
N'SELECT #TempCount = COUNT(*) FROM person WHERE id = 903 AND ('
+ #ClassificationSQL
+ N')'
EXECUTE sp_executesql
#ClassificationSQL,
N'#TempCount INT OUTPUT',
#TempCount = #Counts OUTPUT
SELECT #Counts
See a below sample about how you can get the output of a dynamic query (tested in SQL Server 2008 R2). Actual post from where the idea is taken How to get sp_executesql result into a variable?
DECLARE #retval int;
DECLARE #SQL nvarchar(500);
DECLARE #Param nvarchar(500);
DECLARE #table nvarchar(50)
SELECT #table = N'newperson'
SELECT #SQL = N'SELECT #retvalOUT = MAX(salary) FROM ' + #table;
SET #Param = N'#retvalOUT int OUTPUT';
EXEC sp_executesql #SQL, #Param, #retvalOUT=#retval OUTPUT;
SELECT #retval;
You can make changes to your procedure accordingly.

Set variable to result of executed statement in a sproc

Do you have any good concise tutorials about variable syntax? This is part of a sproc:
Set #sql = 'Set ' + #calc + '= SUM(datalength(' + #column_name + '))/2 from ' + #table_name
exec (#sql)
And it doesn't work - I get an Error converting data type varchar to numeric. Here is the simulated example:
DECLARE #calc numeric(18,2)
DECLARE #sql nvarchar(1500), #column_name nvarchar(50), #table_name nvarchar(50)
Set #column_name = 'EID'
Set #table_name = 'CTY_SUPPORTED'
Set #sql = 'Select #calc = SUM(datalength(' + #column_name + '))/2 from ' + #table_name
exec (#sql)
print #calc
I'm interested in attributing to variable #calc the following value: SUM(datalength(column_x))/2 from table_x
Also if you know syntax lessons (preferably not encyclopedias) - many thanks and gooday!
Set #sql = 'Select #calc = SUM(datalength(' + #column_name + '))/2 from ' + #table_name
exec (#sql)