T-SQL:无法从OLE DB提供程序中获取该行的数据" OraOLEDB.Oracle"对于链接服务器

时间:2018-04-06 18:40:31

标签: sql-server oracle tsql linked-server

错误是:

  

无法从OLE DB提供程序获取该行的数据" OraOLEDB.Oracle"对于链接服务器

我正在尝试将Oracle SQL查询转换为T-SQL。运行此版本的查询时出现错误:

SELECT B.SAAS_ACTIVITY, A.LAST_NAME, A.FIRST_NAME, A.MIDDLE_NAME,  
        B.DIVISION_CODE, B.GRANT_YEAR, B.ACTIVITY_CODE, B.ACT_ACTIVITY_CODE,
        B.COST_CENTER, B.HOURS_BEG, B.LEAVE_ADJ_HOURS, B.CURRENT_MONTH,
        B.HOURS_BEG + B.LEAVE_ADJ_HOURS TOTAL_HOURS, B.PERCENT_WORK, 
        B.DIV_MONTHLY_SALARY, C.DIV_DESCRIPTION,
        B.DIV_SALARY_PLUS_FRINGE - B.DIV_MONTHLY_SALARY FRINGE, 
        B.DIV_SALARY_PLUS_FRINGE
  FROM ORCL_RIVENDELL..BP2K.EMT_EMPLOYEE A, 
ORCL_RIVENDELL..BP2K.LABOR_DISTRIB_MASTER_DETAIL B, 
    ORCL_RIVENDELL..BP2K.ACT_DIVISION C
  WHERE A.ID = B.ID
       AND B.FISCAL_YEAR = :P_SFY
       AND B.DIVISION_CODE = C.DIVISION_CODE
       AND C.DIV_SFY = :P_SFY
       AND B.CURRENT_MONTH >= CASE WHEN :P_FROM_MONTH is null THEN 2 
            ELSE :P_FROM_MONTH
            END
       AND B.CURRENT_MONTH <= CASE WHEN :P_TO_MONTH is null THEN 13 
           ELSE :P_TO_MONTH
           END
       AND B.SAAS_ACTIVITY >= CASE WHEN :P__FROM_OFFICE  is null THEN '4701' 
           ELSE :P_FROM_OFFICE
           END
       AND B.SAAS_ACTIVITY <= CASE WHEN :P__TO_OFFICE  is null THEN '4705' 
           ELSE :P_TO_OFFICE
           END
       AND B.DIVISION_CODE >= CASE WHEN :P__FROM_DIV  is null THEN '0011' 
           ELSE :P_FROM_DIV
           END
      AND B.DIVISION_CODE <= CASE WHEN :P__TO_DIV  is null THEN '9999' 
           ELSE :P_TO_DIV
           END
      AND B.DIVISION_CODE <> '1050'
ORDER BY B.DIVISION_CODE, A.LAST_NAME, B.CURRENT_MONTH

但是如果删除连接以获取DIV_DESCRIPTION,并且只使用DIV_CODE,那么查询运行正常:

SELECT B.SAAS_ACTIVITY, A.LAST_NAME, A.FIRST_NAME, A.MIDDLE_NAME,  
        B.DIVISION_CODE, B.GRANT_YEAR, B.ACTIVITY_CODE, B.ACT_ACTIVITY_CODE,
        B.COST_CENTER, B.HOURS_BEG, B.LEAVE_ADJ_HOURS, B.CURRENT_MONTH,
        B.HOURS_BEG + B.LEAVE_ADJ_HOURS TOTAL_HOURS, B.PERCENT_WORK, 
        B.DIV_MONTHLY_SALARY, B.DIVISION_CODE,
        B.DIV_SALARY_PLUS_FRINGE - B.DIV_MONTHLY_SALARY FRINGE, 
        B.DIV_SALARY_PLUS_FRINGE
  FROM ORCL_RIVENDELL..BP2K.EMT_EMPLOYEE A, 
     ORCL_RIVENDELL..BP2K.LABOR_DISTRIB_MASTER_DETAIL B
  WHERE A.ID = B.ID
       AND B.FISCAL_YEAR = :P_SFY
       AND B.CURRENT_MONTH >= CASE WHEN :P_FROM_MONTH is null THEN 2 
            ELSE :P_FROM_MONTH
            END
       AND B.CURRENT_MONTH <= CASE WHEN :P_TO_MONTH is null THEN 13 
           ELSE :P_TO_MONTH
           END
       AND B.SAAS_ACTIVITY >= CASE WHEN :P__FROM_OFFICE  is null THEN '4701' 
           ELSE :P_FROM_OFFICE
           END
       AND B.SAAS_ACTIVITY <= CASE WHEN :P__TO_OFFICE  is null THEN '4705' 
           ELSE :P_TO_OFFICE
           END
       AND B.DIVISION_CODE >= CASE WHEN :P__FROM_DIV  is null THEN '0011' 
           ELSE :P_FROM_DIV
           END
      AND B.DIVISION_CODE <= CASE WHEN :P__TO_DIV  is null THEN '9999' 
           ELSE :P_TO_DIV
           END
      AND B.DIVISION_CODE <> '1050'
ORDER BY B.DIVISION_CODE, A.LAST_NAME, B.CURRENT_MONTH

获取DIV_DESCRIPTION并不是绝对关键,但我想了解错误发生的原因(我使用Oracle SQL比TSQL更多)。该列在ACT_DIVISION表和LABOR_DISTRIB_MASTER_DETAIL表中定义为VARCHAR2(12)。这是一个数据类型不匹配的东西,还是别的什么?

谢谢, 哈利

1 个答案:

答案 0 :(得分:0)

我建议让Oracle通过OPENQUERY传递查询来为您完成所有繁重的工作,因为Oracle会更加容易(因为您了解Oracle语法)并且速度更快,因为Oracle将自行完成工作它自己的表有自己的索引,只将结果集传回给SQL Server。

注意,由于查询包含在' '中,因此您必须将其中的单个'加倍。

执行此操作时,OLEDB驱动程序应该为您处理所有不稳定的数据类型映射。

语法:

SELECT *
FROM OPENQUERY([ORCL_RIVENDELL],'SELECT B.SAAS_ACTIVITY, A.LAST_NAME, A.FIRST_NAME, A.MIDDLE_NAME,  
        B.DIVISION_CODE, B.GRANT_YEAR, B.ACTIVITY_CODE, B.ACT_ACTIVITY_CODE,
        B.COST_CENTER, B.HOURS_BEG, B.LEAVE_ADJ_HOURS, B.CURRENT_MONTH,
        B.HOURS_BEG + B.LEAVE_ADJ_HOURS TOTAL_HOURS, B.PERCENT_WORK, 
        B.DIV_MONTHLY_SALARY, C.DIV_DESCRIPTION,
        B.DIV_SALARY_PLUS_FRINGE - B.DIV_MONTHLY_SALARY FRINGE, 
        B.DIV_SALARY_PLUS_FRINGE
  FROM BP2K.EMT_EMPLOYEE A, 
       BP2K.LABOR_DISTRIB_MASTER_DETAIL B, 
       BP2K.ACT_DIVISION C
  WHERE A.ID = B.ID
       AND B.FISCAL_YEAR = :P_SFY
       AND B.DIVISION_CODE = C.DIVISION_CODE
       AND C.DIV_SFY = :P_SFY
       AND B.CURRENT_MONTH >= CASE WHEN :P_FROM_MONTH is null THEN 2 
            ELSE :P_FROM_MONTH
            END
       AND B.CURRENT_MONTH <= CASE WHEN :P_TO_MONTH is null THEN 13 
           ELSE :P_TO_MONTH
           END
       AND B.SAAS_ACTIVITY >= CASE WHEN :P__FROM_OFFICE  is null THEN ''4701'' 
           ELSE :P_FROM_OFFICE
           END
       AND B.SAAS_ACTIVITY <= CASE WHEN :P__TO_OFFICE  is null THEN ''4705'' 
           ELSE :P_TO_OFFICE
           END
       AND B.DIVISION_CODE >= CASE WHEN :P__FROM_DIV  is null THEN ''0011'' 
           ELSE :P_FROM_DIV
           END
      AND B.DIVISION_CODE <= CASE WHEN :P__TO_DIV  is null THEN ''9999'' 
           ELSE :P_TO_DIV
           END
      AND B.DIVISION_CODE <> ''1050''
ORDER BY B.DIVISION_CODE, A.LAST_NAME, B.CURRENT_MONTH')

如果需要传递参数,可以使用以下语法:

假设您有一个名为@myDate的参数,您需要传递。

DECLARE @myDate DATETIME=GETDATE()

DECLARE @SQL NVARCHAR(MAX)

SET @SQL = 'SELECT *
            FROM OPENQUERY([ORCL_RIVENDELL],''SELECT *
                                                FROM  BP2K.SOME_TABLE
                                                WHERE ACTIVITYDATE = '''''+CONVERT(VARCHAR,@myDate,120)+''''' '')'

PRINT @SQL
--EXEC SP_EXECUTESQL @SQL

所有这一切,你需要非常小心使用动态SQL,如果你不控制这些参数的输入,这是危险的。你这样开启自己的SQL注入攻击。将参数传递到sp_executesql有更好/更安全的方法,但在使用OPENQUERY时不起作用。如果您可以更好地使用ISDATE()ISNUMERIC()来验证输入,那么如果他们没有通过验证,请不要执行。但你最安全的赌注是永远不要让任何人除了你之外传递这些参数。

相关问题