【问题标题】:How to run query with parameters against a database whose name is in a variable using sp_ExecuteSql如何使用 sp_ExecuteSql 对名称在变量中的数据库运行带参数的查询
【发布时间】:2021-01-21 19:28:02
【问题描述】:

我在 Windows Server 2016 中使用 Microsoft SQL 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 个参数的 proc:数据库名称和项目名称:

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

我想运行上述查询,将@a_project_name 作为参数传递给查询。我想使用sp_executeSQL@a_database_name 变量中提供的数据库运行查询。我该怎么做?

我知道如何在没有sp_executeSQL 的情况下执行此任务。我想知道如何使用sp_executeSQL

【问题讨论】:

    标签: sql sql-server sp-executesql


    【解决方案1】:

    您可以使用以下 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
    

    【讨论】:

    • 但是这个解决方案没有使用sp_executeSQL。我更喜欢使用 sp_executeSQL 的解决方案
    • @srh 现在请检查我是否正确。
    • 不工作。我也希望 @a_database_name 参数化像 @a_project_name
    • 数据库是sql server。对吗?
    • @srh 如果我没记错,那么您不能像我使用项目名称作为参数那样使用数据库名称。但它可以以稍微不同的方式完成。我已经更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    相关资源
    最近更新 更多