[英]T-SQL: cannot get the data of the row from the OLE DB provider “OraOLEDB.Oracle” for linked server
Error is: 错误是:
Cannot get the data of the row from the OLE DB provider "OraOLEDB.Oracle" for linked server
无法从链接服务器的OLE DB提供程序“ OraOLEDB.Oracle”获取行的数据
I'm trying to convert an Oracle SQL query to T-SQL. 我正在尝试将Oracle SQL查询转换为T-SQL。 I get the error when I run this version of the query:
运行此版本的查询时出现错误:
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
But if remove the join to get the DIV_DESCRIPTION, and just go with the DIV_CODE, the query runs fine: 但是,如果删除联接以获取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
Getting the DIV_DESCRIPTION is not absolutely critical, but I would like to understand why the error is occurring (I've worked with Oracle SQL much more than TSQL). 获取DIV_DESCRIPTION并不是绝对关键,但是我想了解为什么会发生错误(与TSQL相比,我使用Oracle SQL的工作更多)。 The column is defined as VARCHAR2(12) in both the ACT_DIVISION table and the LABOR_DISTRIB_MASTER_DETAIL table.
该列在ACT_DIVISION表和LABOR_DISTRIB_MASTER_DETAIL表中均定义为VARCHAR2(12)。 IS this a data type mismatch thing, or something else?
这是数据类型不匹配的东西,还是其他?
Thanks, Harry 谢谢,哈利
I recommend letting Oracle do all the grunt work for you by passing the query over via an OPENQUERY
, its much easier on you (since you know Oracle syntax) and faster, since Oracle will do its own work on its own tables with its own indexes and only pass back the resultset to SQL Server. 我建议让Oracle通过
OPENQUERY
传递查询来为您完成所有繁琐的工作,因为您将使用自己的索引在自己的表上进行自己的工作,这使您的工作更加轻松(因为您知道Oracle语法)并且仅将结果集传递回SQL Server。
Note since the query is contained in ' '
you have to double up the single '
within it. 注意,由于查询包含在
' '
您必须将其中的单个'
加倍'
。
In doing this, the OLEDB driver should handle all the wonky datatype mapping for you. 为此,OLEDB驱动程序应为您处理所有不可靠的数据类型映射。
Syntax: 句法:
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')
If you need to pass parameters, here is the syntax: 如果您需要传递参数,则语法如下:
Let's assume you have a parameter called @myDate you need to pass. 假设您需要传递一个名为@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
All that said, you need to be VERY VERY careful using dynamic SQL, its dangerous if you do not control the input to these parameters. 综上所述,使用动态SQL时要非常小心,如果不控制这些参数的输入,这很危险。 You open yourself to SQL Injection attacks this way.
您可以通过这种方式对SQL注入攻击开放。 There are better/safer ways to pass parameters into
sp_executesql
but it would not work when using an OPENQUERY
. 有更好/更安全的方法可以将参数传递到
sp_executesql
但是在使用OPENQUERY
时不起作用。 If you can validate the input using ISDATE()
or ISNUMERIC()
all the better, don't execute if they don't pass validation. 如果可以使用
ISDATE()
或ISNUMERIC()
更好地验证输入,则如果它们未通过验证,请不要执行。 But your safest bet is to NEVER allow anyone but you to pass these parameters in, ever. 但是,最安全的选择是永远禁止除您之外的任何人传入这些参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.