sql server 链接到 oracle 的服务器在数据存在时返回未找到数据

Posted

技术标签:

【中文标题】sql server 链接到 oracle 的服务器在数据存在时返回未找到数据【英文标题】:sql server linked server to oracle returns no data found when data exists 【发布时间】:2013-10-07 12:57:52 【问题描述】:

我在 SQL Server 中设置了链接服务器来访问 Oracle 数据库。我在 SQL Server 中有一个使用点表示法连接 Oracle 表的查询。我从 Oracle 收到“未找到数据”错误。在 Oracle 方面,我正在访问一个表(不是视图),并且不涉及任何存储过程。

首先,当没有数据时,我应该只得到零行而不是错误。 其次,在这种情况下实际上应该有数据。 三、只在PL/SQL代码中看到ORA-01403错误;从不在 SQL 中。

这是完整的错误信息: 链接服务器“OM_ORACLE”的 OLE DB 提供程序“OraOLEDB.Oracle”返回消息“ORA-01403:未找到数据”。 消息 7346,第 16 层,状态 2,第 1 行 无法从链接服务器“OM_ORACLE”的 OLE DB 提供程序“OraOLEDB.Oracle”获取行的数据。

这里有一些详细信息,但这可能没有任何意义,因为您没有我的表格和数据。 这是有问题的查询:

select *
   from eopf.Batch b join eopf.BatchFile bf
                 on b.BatchID = bf.BatchID
          left outer join [OM_ORACLE]..[OM].[DOCUMENT_UPLOAD] du
                 on bf.ReferenceID = du.documentUploadID;

我不明白为什么会出现“未找到数据”错误。下面的查询使用相同的 Oracle 表并且不返回任何数据,但我没有收到错误 - 我只是没有返回任何行。

select * from [OM_ORACLE]..[OM].[DOCUMENT_UPLOAD] where documentUploadID = -1

下面的查询返回数据。我刚刚从联接中删除了其中一个 SQL Server 表。但是删除批处理表并不会更改从批处理文件返回的行(两种情况下都是 271 行——批处理文件中的所有行都有一个批处理条目)。它仍应将相同的 batchFile 行连接到相同的 Oracle 行。

select *
from eopf.BatchFile bf
   left outer join [OM_ORACLE]..[OM].[DOCUMENT_UPLOAD] du
      on bf.ReferenceID = du.documentUploadID;

此查询返回 5 行。它应该与原始查询中的 5 相同。 (我不能使用它,因为我需要来自 batch 和 batchFile 表的数据)。

       select *
   from [OM_ORACLE]..[OM].[DOCUMENT_UPLOAD] du
   where du.documentUploadId
   in
   (
   select bf.ReferenceID
   from eopf.Batch b join eopf.BatchFile bf
                 on b.BatchID = bf.BatchID);

有人遇到过这个错误吗?

【问题讨论】:

【参考方案1】:

今天我在使用内部联接时遇到了同样的问题。由于创建codechurn 建议的Table Valued Function 或使用user1935511 建议的Temporary Table 或更改cymorg 建议的Join Types 对我来说是没有选择的,我想分享我的解决方案。

我使用Join Hints 将查询优化器推向正确的方向,因为问题似乎是由本地远程表的嵌套循环连接策略引起的。对我来说 HASHMERGEREMOTE 加入提示有效。

对你来说 REMOTE 将不是一个选项,因为它只能用于内部连接操作。所以使用类似下面的东西应该可以工作。

select *
from eopf.Batch b
join eopf.BatchFile bf
  on b.BatchID = bf.BatchID
left outer merge join [OM_ORACLE]..[OM].[DOCUMENT_UPLOAD] du
  on bf.ReferenceID = du.documentUploadID;

【讨论】:

【参考方案2】:

我也遇到了同样的问题。 解决方案 1:将 Oracle 数据库中的数据加载到临时表中,然后加入到该临时表中 - 这里是 a link。

从这篇帖子a link 你可以发现问题可能出在使用左连接上。 我检查了我的问题,并在更改查询后解决了问题。

【讨论】:

【参考方案3】:

在我的例子中,我有一个由链接表组成的复杂视图,3 个基于链接表的视图和一个本地表。我一直在使用内连接,这个问题就显现出来了。将连接更改为左外连接和右外连接(视情况而定)解决了该问题。

【讨论】:

【参考方案4】:

解决此问题的另一种方法是将 Oracle 数据拉回Table Valued Function。这将导致 SQL Server 出去并从 Oracle 检索所有数据并将其放入结果表变量中。出于所有意图和目的,如果您在查询中使用生成的表值函数,Oracle 数据现在对于 SQL Server 是“本地的”。

我相信最初的问题是 SQL Server 正在尝试优化复合查询的执行,其中包括远程 Oracle 查询结果。通过使用表值函数来包装 Oracle 调用,SQL Server 将对函数返回的结果表变量而不是远程查询执行的结果优化复合查询。

CREATE function [dbo].[documents]()
returns @results TABLE (

    DOCUMENT_ID INT NOT NULL,
    TITLE VARCHAR(6) NOT NULL,
    LEGALNAME VARCHAR(50) NOT NULL,
    AUTHOR_ID INT NOT NULL,
    DOCUMENT_TYPE VARCHAR(1) NOT NULL,
    LAST_UPDATE DATETIME
) AS 

BEGIN
INSERT INTO @results
SELECT     CAST(DOCUMENT_ID AS INT) AS DOCUMENT_ID, TITLE, LEGALNAME, CAST(AUTHOR_ID AS INT) AS AUTHOR_ID, DOCUMENT_TYPE, LAST_UPDATE
FROM         OPENQUERY(ORACLE_SERVER, 
                      'select DOCUMENT_ID, TITLE, LEGALNAME, AUTHOR_ID, DOCUMENT_TYPE, FUNDTYPE, LAST_UPDATE
                       from documents')

return
END

然后您可以使用表值函数,因为它是 SQL 查询中的表:

SELECT * FROM DOCUMENTS()

【讨论】:

【参考方案5】:

我通过避免使用 = 运算符解决了这个问题。尝试改用这个:

select * from [OM_ORACLE]..[OM].[DOCUMENT_UPLOAD] where documentUploadID < 0

【讨论】:

以上是关于sql server 链接到 oracle 的服务器在数据存在时返回未找到数据的主要内容,如果未能解决你的问题,请参考以下文章

SQL 2005 - 链接服务器到 Oracle 查询极慢

sql server 2008 链接 ORACLE 问题

SQL Server中创建Oracle的链接服务器

SQL Server 2008 R2 链接 Oracle

使用带有 oracle 的链接服务器更新 SQL Server 上的查询

从 Microsoft SQL Server 搜索链接服务器 (Oracle) 中的列名 [重复]