【问题标题】:Pass a table as parameter in openquery在 openquery 中将表作为参数传递
【发布时间】:2021-02-26 12:23:34
【问题描述】:

我创建了一个数据类型并声明了一个这种类型的表,我打算将其作为参数传递给 OPENQUERY 语句。 OPENQUERY 返回对象没有列的错误。
首先表参数定义如下:

CREATE TYPE LooseTimecardsTableType AS TABLE ([LABORKEY] [float] NULL)          
GO

DECLARE @DataTable AS LooseTimecardsTableType
INSERT INTO @DataTable
SELECT DISTINCT WOBase.LABORKEY
FROM Lab_WO_DataWH AS WOBase 
left outer JOIN Lab_hrs_DataWH LabHrsWH ON LabHrsWH.WORKORDERLABORKEY = WOBase.LABORKEY
WHERE LabHrsWH.WORKORDERLABORKEY IS NULL AND WOBase.LABORKEY IS NOT NULL AND WOBase.LABORPRICE <> 0 

数据表返回LABORKEY 的单列,我想用它来限制来自OPENQUERY 的记录数。这又被定义如下:

DECLARE @SQLString NVARCHAR(500), @TableVariable LooseTimecardsTableType
SET @SQLString =  N'SELECT * FROM OPENQUERY(Remoteserver, ''SELECT DISTINCT
    DA.USERNAME, DA.WORKORDERLABORKEY, LB.PERFORMEDBY 
    FROM
    REMOTE.WORKORDERDETAILAUDITS DA
    JOIN REMOTE.WORKORDERLABORBASE LB ON LB.LABORKEY = DA.WORKORDERLABORKEY
    JOIN @TableVariable ON @TableVariable.LABORKEY = LB.LABORKEY
    WHERE DA.WORKORDERAUDITCATEGORY = 0'')'

EXECUTE sp_executesql @SQLString, N'@TableVariable LooseTimecardsTableType READONLY', @DataTable

请协助使其正常工作

【问题讨论】:

  • 您不能将参数传递给OPENQUERY@TableVariableOPENQUERY 的第二个参数中被引用,因此它没有上下文。
  • 乍一看,您似乎可以将表变量加入到您的 OPENQUERY 结果中,而不是使用动态 SQL,但这取决于数据。如有查询问题,请始终提供示例数据和预期结果(文本格式,而不是屏幕截图)。
  • 你是对的,表变量可以连接到 OPENQUERY 结果。在这些情况下,OPENQUERY 运行非常缓慢。参数的重点实际上是加速 OPENQUERY,我希望它在 OPENQUERY 中工作
  • 除了OPENQUERY不支持参数外,表值参数也不能通过其他机制进行远程访问(链接服务器,EXECUTE .. AT)。由于这只是一个标量集合,您可以将值插入到字符串中(即生成 IN 子句),或生成 INSERT ... FROM (VALUES ...) 语句以在远程端(或实际上是 TVP)生成临时表然后你加入。或者,如果远程数据不是太大,则先将其拉过来,然后再处理它(即让山来找你)。
  • 我必须承认,加入float 似乎是一个非常糟糕的选择。

标签: sql sql-server tsql openquery


【解决方案1】:

您可以使用 where 子句将填充表的 select 语句转换为视图,然后将视图连接到远程服务器上的表,而不是使用表变量。

【讨论】:

    【解决方案2】:

    表变量不能作为参数传递给 OPENQUERY。由于我的表只有一列,我能够将其转换为字符串并将字符串作为参数传递给 OPENQUERY。我在一个接受表变量的过程中做到了这一点。将表解析为字符串后,该过程还运行 OPENQUERY。

    CREATE PROCEDURE  PRM_LIST ( @TableVariable LooseTimecardsTableType  READONLY)
    AS
    DECLARE
    @LBKY_NVAR NVARCHAR(2500),
    @POINTER INT,
    @SQLString NVARCHAR(max)
    
    SELECT @POINTER =  MIN(LABORKEY) FROM @TableVariable
    WHILE @POINTER IS NOT NULL
    BEGIN
    SET @LBKY_NVAR = IIF(@LBKY_NVAR IS NULL,'('+''''+ CONVERT(VARCHAR,@POINTER) + '''',
    @LBKY_NVAR + ',' + ''''+ CONVERT(VARCHAR,@POINTER) + '''')
    SELECT @POINTER =  MIN(LABORKEY) FROM @TableVariable WHERE LABORKEY > @POINTER
    END
    SET @LBKY_NVAR = @LBKY_NVAR +  ')'
    SET @LBKY_NVAR = REPLACE(@LBKY_NVAR,'''','''''')
    
    SET @SQLString =
    N'SELECT * FROM OPENQUERY(REMOTE, ''SELECT DISTINCT
    DA.USERNAME, DA.WORKORDERLABORKEY, LB.PERFORMEDBY 
    FROM
    REMOTE.WORKORDERDETAILAUDITS DA
    JOIN REMOTE.WORKORDERLABORBASE LB ON LB.LABORKEY = DA.WORKORDERLABORKEY
    WHERE DA.WORKORDERAUDITCATEGORY = 0
    AND LB.LABORKEY IN '+CAST(@LBKY_NVAR AS nvarchar(2500))+ N'
    '')'
    EXEC (@SQLString)
    GO
    

    过程调用是:

    EXECUTE PRM_LIST @DATATABLE
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-13
      • 2015-04-17
      • 2012-11-27
      相关资源
      最近更新 更多