如何 运行 使用参数查询名称在变量中的数据库 sp_ExecuteSql
How to run query with parameters against a database whose name is in a variable using sp_ExecuteSql
我正在 Microsoft SQL Server 2016 Windows Server 2016.
我有一个带有 1 个字符串类型参数的查询。
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;
其中 @ProjectName
是 varchar(50) 类型。
我必须编写一个接收 2 个参数的过程:数据库名称和项目名称:
@a_database_name varchar(100),
@a_project_name varchar(50)
我想 运行 上面的查询将 @a_project_name
作为参数传递给查询。我想 运行 使用 sp_executeSQL
对 @a_database_name
变量中提供的数据库进行查询。我该怎么做?
我知道如何在没有 sp_executeSQL
的情况下执行此任务。我想知道如何使用 sp_executeSQL
?
您可以使用下面的 SQL 创建该过程:
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
但它有 SQL 注入风险 - 如果提供 @a_database_name
包含其中 ";DROP DATABASE"
。但是,如果您信任调用此过程的系统,那么您就可以开始了。
或者您可以使用下面没有“使用数据库名称”的查询:
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
用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
修改后的答案:
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
我正在 Microsoft SQL Server 2016 Windows Server 2016.
我有一个带有 1 个字符串类型参数的查询。
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;
其中 @ProjectName
是 varchar(50) 类型。
我必须编写一个接收 2 个参数的过程:数据库名称和项目名称:
@a_database_name varchar(100),
@a_project_name varchar(50)
我想 运行 上面的查询将 @a_project_name
作为参数传递给查询。我想 运行 使用 sp_executeSQL
对 @a_database_name
变量中提供的数据库进行查询。我该怎么做?
我知道如何在没有 sp_executeSQL
的情况下执行此任务。我想知道如何使用 sp_executeSQL
?
您可以使用下面的 SQL 创建该过程:
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
但它有 SQL 注入风险 - 如果提供 @a_database_name
包含其中 ";DROP DATABASE"
。但是,如果您信任调用此过程的系统,那么您就可以开始了。
或者您可以使用下面没有“使用数据库名称”的查询:
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
用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
修改后的答案:
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