Column name set in stored procedure but not working - sql-server-2008

Column name set in stored procedure but not working. But when I run this script empty rows appears. What I do this for run this script?
Create Procedure Test
()
AS
BEGIN
Declare #columnName nvarchar(50);
set #columnName ='StoreName';
SELECT *
FROM testtable
WHERE #columnName = 'storemanager'
END

You need to use dynamic SQL because you can't reference a column with a variable - T-SQL just doesn't parse things in that order. Try something like:
CREATE PROCEDURE dbo.Test
#columnName NVARCHAR(50),
#value NVARCHAR(4000)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'SELECT * FROM dbo.testtable WHERE '
+ QUOTENAME(#columnName) + ' = #value;';
EXEC sp_executesql #sql, N'#value NVARCHAR(4000)', #value;
END
GO
QUOTENAME() wraps the column in [square brackets] and hopefully protects you from SQL injection. You should also read these posts:
Bad habits to kick : using SELECT * / omitting the column list
Bad habits to kick : avoiding the schema prefix
My stored procedure "best practices" checklist

Related

Is it possible to write a variable after SELECT?

It is necessary to write a procedure that makes a request, which, in turn, should output all the objects of a particular column.
Here is what I tried:
CREATE PROCEDURE AttributeRequest(n CHAR(200))
begin
SELECT n FROM table;
end
But this variable is perceived as the name of the column itself and nothing comes out.
Tell me how to make such a request by the attribute of the object, please
I searched a bit, read the answers below, and I managed to implement this task in the following way:
CREATE PROCEDURE AttributeRequest(n CHAR(200))
begin
SET #t =CONCAT("SELECT ",n ," FROM table");
PREPARE e FROM #t;
EXECUTE e;
end
you will have to use dynamic sql for this
CREATE PROCEDURE AttributeRequest(#n CHAR(200)) AS
begin
declare #query varchar(1000);
set #query = 'select ['+#n+'] FROM table;
exec AttributeRequest #query
end
then you can excute it ,
exec AttributeRequest 'columnname'

Store a table column name as variable in sql server

I have a sql server stored procedure where I want the table column name to be stored as variable.But I am finding it difficult.
CODE
ALTER PROCEDURE [dbo].[GetLeaveDays]
-- Add the parameters for the stored procedure here
#LeaveType varchar,#AdminId int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT #LeaveType FROM CompulsoryLeave WHERE AdminId =#AdminId
END
Where the #Leavetype is the name of the table column.
EDIT
This is how I execute the stored procedure
GetLeaveDays 'Maternity',1
Use dynamic SQL as suggested. In your case you could use the following T-SQL.
You can read docs for dynamic SQL at Dynamic SQL in SQL Server
Keep in mind to always use sp_executesql to execute your dynamically formed queries since it's more secure that using EXEC (#query).
DECLARE #queryString nvarchar(MAX);
SET #queryString = 'SELECT ' + #LeaveType + ' WHERE AdminId = #AdminId';
EXECUTE sp_executesql #queryString,
N'#AdminId int',
#AdminId = #AdminId;
Using the above approach, your stored procedure would now look like the following.
ALTER PROCEDURE [dbo].[GetLeaveDays] -- Add the parameters for the stored procedure here
#LeaveType varchar(5000),
#AdminId int
AS
BEGIN
SET NOCOUNT ON;
DECLARE #queryString nvarchar(MAX);
SET #queryString = 'SELECT ' + #LeaveType + 'FROM CompulsoryLeave WHERE AdminId = #AdminId';
EXECUTE sp_executesql #queryString,
N'#AdminId int',
#AdminId = #AdminId;
END
you can use sp_executesql command for this purpose. You can read this Article to get a nice review on dynamic SQL.
DECLARE #sqlCommand nvarchar(max);
SET #sqlCommand = 'SELECT ' + #LeaveType + ' FROM CompulsoryLeave WHERE AdminId = '''+#AdminId+''''
EXECUTE sp_executesql #sqlCommand, N'#AdminId int', #AdminId = #AdminId;

How to Update values in sql by Muliple Column name in Sql

I want add values to multiple columns
ALTER PROCEDURE DynamicInsertQuery
#ColumnName VARCHAR(MAX),
#RiD VARCHAR(50)
AS
BEGIN
DECLARE #DynamicQuery NVARCHAR(MAX)
SET #DynamicQuery = 'UPDATE tbl_route_info SET ('+ #ColumnName +') = (1) WHERE RouteId=('+#RiD+')'
EXEC(#DynamicQuery)
END
This is the code I tried.
I run this procedure like this
DynamicInsertQuery '(1,2)','10'
I suspect you want something like this:
ALTER PROCEDURE DynamicInsertQuery (
#ColumnName VARCHAR(MAX),
#RiD VARCHAR(50)
) AS
BEGIN
DECLARE #DynamicQuery NVARCHAR(MAX);
SET #DynamicQuery = 'update tbl_route_into set #ColumnName = 1 where RouteId = #RiD';
SET #DynamicQuery = REPLACE(#DynamicQuery, '#ColumnName', #ColumnName);
EXEC sp_executesql #DynamicQuery, N'#RiD VARCHAR(50)', #RiD = #RiD;
END;
Notes:
You have too many parentheses in your version.
If you are learning to use dynamic SQL, then learn sp_executesql -- and how to use it to pass parameters.
You cannot pass names of things (columns, tables, etc.) as parameters, so that has to be placed directly in the string.
You can pass values into the string, such as #RiD.

Error passing parameter to stored procedure

I have the following stored procedure:
SET QUOTED_IDENTIFIER OFF;
GO
ALTER PROCEDURE [transactiondb] #dbname1 NVARCHAR(128)
AS
DECLARE #query VARCHAR(1000);
SET #query = "SELECT TOP 10*
FROM #dbname1.dbo.transaction";
EXEC (#query);
GO
When I execute the stored procedure I get the following error:
Must declare the scalar variable "#dbname1"
I am pretty sure this is something to do with the way the variable is being passed, but I am really struggling to understand what is happening or how to correct?
Try with this. it works for me,
Alter PROCEDURE [transactiondb] #dbname1 NVARCHAR(128)
AS
DECLARE #query VARCHAR(1000);
SET #query = 'SELECT TOP 10 *
FROM ' +#dbname1+'.dbo.transaction';
EXEC (#query);
Go

How to return only a single resultset in a stored procedure

Consider the following stored procedure :
create procedure [dbo].[MyTest] ( #p_SqlStatement nvarchar(max) )
as
begin
exec sp_executesql #p_SqlStatement
if ##ROWCOUNT = 1
begin
select 1;
end
else if ##ROWCOUNT <> 1
begin
select 0;
end
end
This stored procedure currently returns 2 datasets, one with the exec sp_executesql #p_SqlStatement data, and the other one would be either 1 or 0. Is there a way to suppress the first dataset? I mean, would it be possible that this stored procedure returns only 1 or 0 ?
I tried adding a RAISERROR( 'MyError', 18, 1 ) right after the exec sp_executesql #p_SqlStatement and then in the catch block select something else, but the first result set is always returned to my stored procedure caller...
You can embed the query in an if exists(.
alter procedure [dbo].[MyTest] ( #p_SqlStatement nvarchar(max) )
as
begin
set #p_SqlStatement = 'if exists('+#p_SqlStatement+') select 1 else select 0'
exec sp_executesql #p_SqlStatement
end
There are however some queries where this won't fly.
Multiple statements
Queries terminated with ;
Queries that uses CTE's
There might be more but these are the ones I can think of right now.
Update:
You could try to use openrowset.
alter procedure [dbo].[MyTest] ( #p_SqlStatement nvarchar(max) )
as
begin
declare #S nvarchar(max)
set #S =
'if exists(
select *
from openrowset(
''SQLNCLI'',
''Server=localhost;Trusted_Connection=yes;'',
'+quotename(#p_SqlStatement, '''')+'
) as T
)
select 1
else
select 0'
exec (#S)
end
I have never used this in productions but from the tests I made i looks like it should work with SP's, CTE's and multiple lines.
You have to allow ad hoc distributed queries.
You may try the NOCOUNT statement ( http://msdn.microsoft.com/en-us/library/ms189837.aspx )
create procedure [dbo].[MyTest] ( #p_SqlStatement nvarchar(max) )
as
begin
SET NOCOUNT ON;
exec sp_executesql #p_SqlStatement
if ##ROWCOUNT = 1
begin
select 1;
end
else if ##ROWCOUNT <> 1
begin
select 0;
end
SET NOCOUNT OFF;
end
try this approach:
declare #mycount bigint
exec sp_executesql N'select #mycount = count(name) from Page where name like ''P%''', N'#mycount bigint OUTPUT', #mycount OUTPUT
select #mycount
It is important that your statement #p_SqlStatement incorporates a count.
If that is not the case, meaning your want to run this sp for any SQL you come upon, then this is no help. I don't think your can't suppress output of the sp_executesql.
Edit: You could also try this:
declare #mycount bigint
exec sp_executesql N'SELECT * INTO ##MyTempTable from Page where name like ''P%'''
select count(*) from ##MyTempTable
drop table ##MyTempTable
This means that you will have to add the following to every query (don't know if this works with sp's?) "SELECT * INTO ##MyTempTable FROM " - That shouldn't be to hard.
"##temptables" are global scoped temptables. Which means that they are also available outside the sp_executesql sp. You must drop the table explicitly.
I was not able to find any other workaround than using the suggested OPENROWSET. However, I found a way to be independant from the servername / instance. I still have to reconfigure the server to accept ad hoc distributed queries. Here is the final result :
create procedure [dbo].[MyTest] ( #p_SqlStatement nvarchar(max) )
as
begin
declare #sql nvarchar(max) = N'SELECT * INTO ##TMP FROM OPENROWSET(''SQLOLEDB'',''Server=' + ##SERVERNAME + ';Trusted_Connection=Yes;'',''' + #p_SqlStatement + ''')';
exec sp_executesql #sql
if ( select COUNT(1) from ##TMP ) = 1
begin
select 1;
end
else
begin
select 0;
end
drop table ##TMP;
end
This solution has it's limitations :
Every column in the #p_SqlStatement must have a name
I have to enable Ad Hoc Distributed Queries on my server.
I have to use #sql variable along with sp_executesql on the OPENROWSET because I was not able to use variables inside OPENROWSET in another way, so this makes dynamic SQL on an OPENROWSET, which is pretty bad performance-wise.
I do reconfigure the server using the following script :
sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE;
GO