How to get value by dynamic field Name using sql select query - sql

I am passing dynamic column name base that column name to get the value and below i my table
Table_CandidateInfo
Id Name Age City
1 Mazhar 30 Gulbarga
20 Khan 29 Bidar
Example1
Declare #ColumnName varchar(100), #Id int
set #ColumnName='Age'
set #Id=20
select * from Table_CandidateInfo where ID=#Id and
I am not able to pass ColumnName with and query because column name is dynamic pass by code. My output should be
29
Example2: If my #ColumnName='City' and #Id=20 then output should be like below
Bidar

I think what you are actually after is the below:
DECLARE #ColumnName sysname, #Id int;
SET #Id = 29;
SET #ColumnName = N'Age';
DECLARE #SQL nvarchar(MAX);
SET #SQL = N'SELECT ' + QUOTENAME(#ColumnName) + N' FROM dbo.Table_CandidateInfo WHERE Id = #Id;';
--PRINT #SQL; --Your debugging friend
EXEC sp_executesql #SQL, N'#Id int', #Id = #Id;

Alas, you cannot pass identifiers as parameters. You need to use dynamic SQL:
declare #columnName varchar(100);
declare #Id int;
set #ColumnName = 'Age' ;
set #Id = 20;
declare #sql nvarchar(max);
set #sql = '
select *
from Table_CandidateInfo
where [columnName] = #Id';
select #sql = replace(#sql, '[columnName]', quotename(#columnName));
exec sp_executesql #sql,
N'#id int',
#id=#id;

Related

Set count to variable

I would like to assign the number of rows of my table to a variable.
DECLARE #ROW_COUNT nvarchar(1000);
SET #sql_row_count = 'SELECT COUNT(*) FROM ' + #TABLE_NAME;
EXEC sp_executesql #sql_row_count, #ROW_COUNT OUTPUT;
SET #ROW_COUNT = cast(#ROW_COUNT as int);
SELECT #ROW_COUNT;
#ROW_COUNT returns null.
Thank for help.
Comments on your existing query
#ROW_COUNT should be integer. You don't need to use CAST() if you defined it as integer.
You need to assign #ROW_COUNT to COUNT(*).
use QUOTENAME() on the #TABLE_NAME to avoid sql injection.
define the parameters for sp_executesql.
Modified query as follow
DECLARE #ROW_COUNT INT;
DECLARE #sql_row_count NVARCHAR(MAX)
SET #sql_row_count = 'SELECT #ROW_COUNT = COUNT(*) FROM ' + QUOTENAME(#TABLE_NAME);
-- print out for verification
PRINT #sql_row_count
EXEC sp_executesql #sql_row_count, N'#ROW_COUNT INT OUTPUT', #ROW_COUNT OUTPUT;
-- SET #ROW_COUNT = cast(#ROW_COUNT as int);
SELECT #ROW_COUNT;
You need to alter the dynamic query by adding a variable that will
be assigned the value Count(*) and change the call sp_executesql by adding a description of this variable.
Declare #ROW_COUNT Int;
Declare #TABLE_NAME sysname = 'TableName';
Declare #sql_row_count nVarChar(max);
SET #sql_row_count = 'SELECT #ROW_COUNT=COUNT(*) FROM ' +
#TABLE_NAME;
EXEC sp_executesql #sql_row_count, N'#ROW_COUNT Int OUTPUT',
#ROW_COUNT=#ROW_COUNT OUTPUT
SELECT #ROW_COUNT;

SQL Server Default Column value from function

I want to set default value to Id column in Person table with a function
that goes like this:
Function:
IF OBJECT_ID ( 'GetLastId','FN') IS NOT NULL
DROP function GetLastId;
GO
CREATE FUNCTION [dbo].[GetLastId]
(#TableName nvarchar(max))
RETURNS int
AS
BEGIN
DECLARE #LastId int;
DECLARE #sql nvarchar(max);
SET #sql = 'SELECT #LastId = ISNULL(MAX(Id), 0) + 1 FROM ' + #TableName + ';'
EXECUTE sp_executesql #sql, N'#LastId int output', #LastId = #LastId output;
RETURN #LastId
END
and then:
UPDATE Person
SET Id = dbo.GetLastId('Person')
Running this code throws an error:
Only functions and some extended stored procedures can be executed from within a function.
So how to fix this and make it work as a default value?
And please do not say "Use triggers..." as I intend to use it with Entity Framework Core as default value for primary keys.
Thanks
You want a stored procedure, not a function:
create procedure [dbo].[GetLastId] (
#TableName nvarchar(max),
#LastId int output
) as
begin
declare #sql nvarchar(max);
set #sql = 'select #LastId = ISNULL(MAX(Id), 0) + 1 from ' + #TableName + ';'
EXECUTE sp_executesql #sql,
N'#LastId int output',
#LastId=#LastId output;
end;
You should also use quotename() around the table name to prevent unexpected things from happening.
Then you would call this as:
declare #lastId int;
exec dbo.GetLastId('Person', #lastid output);
update Person
set Id = #lastId;
You need to create stored procedure instead of function
create procedure [dbo].[GetLastId] (
#TableName nvarchar(max),
#ColumnName nvarchar(200),
#LastId int output
) as
begin
declare #sql nvarchar(max);
set #sql = 'select #LastId = ISNULL(MAX('+ #ColumnName +'), 0) + 1 from ' + #TableName + ';'
EXECUTE sp_executesql #sql,
N'#LastId int output',
#LastId=#LastId output;
end;
Then you can execute sp like below
declare #lastId int
exec dbo.GetLastId 'Person', 'Id' , #lastid output;
select #lastId
update Person
set Id = #lastId;

Issue with using like with a wildcard in dynamic SQL statement

I am trying to use a dynamic SQL statement in a stored procedure to filter a query depending on the input from a user. I am starting basic with just one parameter that needs to find matching forenames in the database.
CREATE PROCEDURE dbo.uspFilter
#FirstName varchar(100) = null,
#Debug bit = 1
AS
DECLARE #SQL nvarchar(max);
DECLARE #Params nvarchar(max);
DECLARE #Search nvarchar(300);
SELECT #Params = N'#FirstName varchar(300) = null'
SELECT #SQL = N'SELECT * FROM Table WHERE 1=1'
IF #FirstName IS NOT NULL
SELECT #Search = N'#FirstName' + N'%'''
SELECT #SQL = #SQL + N' AND Forename LIKE ''' + #Search
IF #Debug = 1
#PRINT #SQL
EXEC sp_executeSQL #SQL, #Params, #FirstName = #FirstName;
GO
EXEC dbo.uspFilter #FirstName = 'Test', #Debug = 1;
GO
The output of the debug statement looks correct but it is not returning any results:
SELECT * FROM Table WHERE 1=1 AND Forename LIKE '#FirstName%'
EDIT: This is a meant to be a trimmed down version of what I am looking for - I will be using multiple parameters with different search criteria.
This is how you need to do it:
CREATE PROCEDURE dbo.uspFilter
#Search varchar(300) = null,
#Debug bit = 1
AS
DECLARE #SQL nvarchar(max);
DECLARE #Params nvarchar(max);
SELECT #Params = N'#FirstName varchar(300)';
SELECT #SQL = N'SELECT * FROM [Table]';
IF #FirstName IS NOT NULL BEGIN
SET #SQL = #SQL + N' WHERE Forename LIKE #FirstName + ''%'';';
END ELSE BEGIN
SET #SQL = #SQL + N';';
END
IF #Debug = 1
PRINT #SQL;
EXEC sp_executeSQL #SQL, #Params, #FirstName = #Search;
GO
EXEC dbo.uspFilter #Search = 'Steve', #Debug = 1;
Note that although Crowcoder's comment about SQL Injection is important, you can write dynamic SQL that doesn't allow for Injection. Such as the above.
Edit: Couple of slight corrections.
CREATE PROCEDURE dbo.uspFilter
#Search varchar(300) = null,
#Debug bit = 1
AS
DECLARE #SQL nvarchar(max);
DECLARE #Params nvarchar(max);
SELECT #Params = N'#FirstName varchar(300)';
SELECT #SQL = N'SELECT * FROM [YourTable]';
IF #Search IS NOT NULL BEGIN
SET #SQL = #SQL + N' WHERE Forename LIKE #FirstName;';
END ELSE BEGIN
SET #SQL = #SQL + N';';
END
IF #Debug = 1
PRINT #SQL;
EXEC sp_executeSQL #SQL, #Params, #FirstName = #Search;
GO
EXEC dbo.uspFilter #Search = 'Rameshbhai%', #Debug = 1;
go
pass parameter with wildcard values like 'searchtext%'
You can also apply dynamic where condition as below without make dynamic query, please have look at below sample example. You can join other filter by applying AND where clause with below example.
Declare #firstName VARCHAR(50)='sa'
SELECT
*
FROM Table
WHERE
(
(Forename LIKE '%'+#firstName+'%' AND #firstName!='')
OR
(#firstName='')
)

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;

Get SQL result into variable

Here is what I have so far. I want to store the query result into an int variable but I get null so far. After execute, both #query and #countrow are both null. Any suggestion would be great.
SET #query = N'select #countrow=count(*) from ' + #tablename
EXECUTE sp_executesql #query
DECLARE #i INT, #sql NVARCHAR(512), #tablename varchar(200) = 'tbl'
SET #sql = N'SELECT #i = COUNT(*) FROM ' + #tablename
EXEC sp_executesql
#query = #sql,
#params = N'#i INT OUTPUT',
#i = #i OUTPUT
PRINT #i
Take a look at SQL Fiddle
You need to use the OUTPUT keyword, similar to this:
declare #query nvarchar(max)
declare #countrow int
declare #tablename varchar(50)
SET #query = N'select #cnt=count(*) from ' + #tablename
EXECUTE sp_executesql #query, N'#cnt int OUTPUT', #cnt=#countrow OUTPUT
select #countrow as countrow -- to get the result