Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
254 views
in Technique[技术] by (71.8m points)

sql - How to run query with parameters against a database whose name is in a variable using sp_ExecuteSql

I am working with Microsoft SQL Server 2016 in Windows Server 2016.

I have a query with 1 parameter, string type.

select PH.project_name, PD.employee_id, E.first_name, E.last_name 
from project_header PH 
inner join project_detail PD on PD.project_id = PH.project_id
inner join employee E on E.employee_id = PD.employee_id
where PH.project_name = @ProjectName
order by 1, 2;

where @ProjectName is varchar(50) type.

I have to write a proc which receives 2 arguments: database name and project name:

@a_database_name varchar(100),
@a_project_name varchar(50)

I want to run the above query passing @a_project_name as parameter to the query. And I want to run the query against the database provided in @a_database_name variable using sp_executeSQL. How can I do that?

I know how to perform this task without sp_executeSQL. I want to know how to do it with sp_executeSQL?

question from:https://stackoverflow.com/questions/65834459/how-to-run-query-with-parameters-against-a-database-whose-name-is-in-a-variable

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use below SQL to create that procedure:

create procedure ProcName  @a_database_name varchar(100),@a_project_name varchar(50)
as
begin

EXEC('USE ' + @a_database_name + ';select PH.project_name, PD.employee_id, E.first_name, E.last_name 
from project_header PH 
inner join project_detail PD on PD.project_id = PH.project_id
inner join employee E on E.employee_id = PD.employee_id
where PH.project_name= '+@a_project_name+'  order by 1, 2;')
end

But it has SQL injection risk- if @a_database_name is provided contains in it ";DROP DATABASE". But if you trust the system that is calling this procedure you are good to go.

Or you might use below query without "use databasename" in it:

create procedure ProcName  @a_database_name varchar(100),@a_project_name varchar(50)
as
begin

EXEC('select PH.project_name, PD.employee_id, E.first_name, E.last_name 
from '+@a_database_name+'.dbo.project_header PH 
inner join project_detail PD on PD.project_id = PH.project_id
inner join employee E on E.employee_id = PD.employee_id
where PH.project_name= '+@a_project_name+'  order by 1, 2;')
end

Query with sp_executesql:

create procedure ProcName  @a_database_name varchar(100),@a_project_name varchar(50)
as
begin
DECLARE  @SqlStatment AS NVARCHAR(1000)
SET @SqlStatment = 'select PH.project_name, PD.employee_id, E.first_name, E.last_name 
from '+@a_database_name+'.dbo.project_header PH 
inner join project_detail PD on PD.project_id = PH.project_id
inner join employee E on E.employee_id = PD.employee_id
where PH.project_name= @a_project_name  order by 1, 2;'

EXECUTE sp_executesql @SqlStatment ,N'@a_project_name varchar',@a_project_name


end

Revised Answer:

create procedure ProcName  @a_database_name varchar(100),@a_project_name varchar(50)
as
begin

declare @sp_executesql as nvarchar(1000)

SELECT @sp_executesql = quotename(@a_database_name) + '.sys.sp_executesql'
EXEC @sp_executesql N'select PH.project_name, PD.employee_id, E.first_name, E.last_name 
from project_header PH inner join project_detail PD on PD.project_id = PH.project_id
inner join employee E on E.employee_id = PD.employee_id
where PH.project_name= @a_project_name  order by 1, 2;',N'@a_project_name nvarchar(100)', @a_project_name;

end

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...