错误是:
无法从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)。这是一个数据类型不匹配的东西,还是别的什么?
谢谢, 哈利
答案 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()
来验证输入,那么如果他们没有通过验证,请不要执行。但你最安全的赌注是永远不要让任何人除了你之外传递这些参数。