在SQL多部分标识符中连接数据库名称

时间:2017-03-28 20:49:44

标签: sql-server sql-server-2012

我正在编写存储过程,并且我试图在FROM之后连接多部分标识符中的数据库名称,但没有成功。这是我试过的一种方法,但它不起作用

INSERT INTO CONTROL_LOGISTICA.dbo.ITEMS_TRAMITE (NRODCTO, TIPODCTO, PRODUCTO, EMPRESA, CODUSUARIO, CODUBICA, CANTIDAD, CCHECK_HIJO) 
    SELECT 
        @pNrodcto, @pTipodcto, 
        M.PRODUCTO, @pEmpresa, @pUsuario,
        M.CODUBICA, M.CANTIDAD, 0
    FROM 
        "@mEmpresa".dbo.MVTRADE M WITH(NOLOCK) -- Here I'm stuck
    INNER JOIN 
        Dbo.vReporteMercia_ESP P ON P.PRODUCTO = M.PRODUCTO
    WHERE 
        M.CANTIDAD <> 0 AND M.Origen = 'FAC' 
        AND M.NRODCTO = @pNrodcto AND M.TIPODCTO = @pTipodcto

我直接从存储过程中获取变量

@pEmpresa AS char(20)

我知道我可以IF喜欢

IF (@pEmpresa = 'John Doe')
 BEGIN
 --..... and the query here
 END

是否可以使用变量连接数据库名称?怎么样?或者我应该使用IF

2 个答案:

答案 0 :(得分:4)

你必须使用动态sql来做类似的事情。

declare @sql nvarchar(max);
declare @params nvarchar(max);

set @params= N'@pNrodcto int, @pTipodcto int, @pUsuario int, @pEmpresa char(20)';

set @sql = N'INSERT INTO CONTROL_LOGISTICA.dbo.ITEMS_TRAMITE (NRODCTO, TIPODCTO, PRODUCTO, EMPRESA, CODUSUARIO, CODUBICA, CANTIDAD, CCHECK_HIJO) 
  SELECT @pNrodcto,@pTipodcto,M.PRODUCTO,@pEmpresa,@pUsuario,M.CODUBICA,M.CANTIDAD,0
  FROM '+db_name(db_id(@pEmpresa))+'.dbo.MVTRADE M WITH(NOLOCK) --Here im stuck
  INNER JOIN Dbo.vReporteMercia_ESP P ON P.PRODUCTO = M.PRODUCTO
  WHERE M.CANTIDAD <> 0 AND M.Origen = ''FAC'' 
  AND M.NRODCTO = @pNrodcto AND M.TIPODCTO = @pTipodcto';
exec sp_executesql @sql, @params, @pNrodcto, @pTipodcto, @pUsuario, @pEmpresa;

为了避免将参数直接连接到已执行的sql字符串,我将参数包装在对db_name()db_id()的调用中。对于无效的数据库名称,这将返回null,但不会阻止某人引用您不希望它们访问的数据库。考虑将参数值与白名单进行比较。

参考:

答案 1 :(得分:1)

不是使用不同的数据库名称动态创建查询,而是动态创建数据库连接,并从查询中省略此数据库名称。而是指定第二个表(Dbo.vReporteMercia_ESP)的数据库名称。我假设另一个表总是来自同一个数据库。

根据连接类型,您必须在连接字符串中动态设置Initial Catalog=<database name>Database=<database name>

SELECT ...
FROM 
    dbo.MVTRADE M WITH(NOLOCK) -- Database from dynamic connection
INNER JOIN 
    MyNonDynamicDatabase.dbo.vReporteMercia_ESP P ON P.PRODUCTO = M.PRODUCTO
...