【问题标题】:SQL Server OpenQuery() behaving differently then a direct query from TOADSQL Server OpenQuery() 的行为与来自 TOAD 的直接查询不同
【发布时间】:2013-07-31 19:10:19
【问题描述】:

以下查询在使用 TOAD(使用本机 Oracle 驱动程序)直接针对 Oracle 11 运行时可以高效运行

select ... from ... where ...
and srvg_ocd in (
  select ocd
   from rptofc
  where eff_endt = to_date('12/31/9999','mm/dd/yyyy')
    and rgn_nm = 'Boston'
) ...
;

如果通过openquery() 从 SQL Server 2008 传递到同一个 Oracle 数据库,则返回完全相同的查询“从不”。 SQL Server 有一个使用 Oracle Provider OLE DB 驱动程序到 Oracle 数据库的链接。

select * from openquery( servername, '
  select ... from ... where ...
  and srvg_ocd in (
    select ocd
     from rptofc
    where eff_endt = to_date(''12/31/9999'',''mm/dd/yyyy'')
      and rgn_nm = ''Boston''
  ) ...
');

查询没有在合理的时间内返回,用户终止了查询。我不知道它最终是否会返回正确的结果。

直接 TOAD 查询高效工作且 openquery() 版本“从不”返回的结果是可重现的。

openquery() 的小修改给出了正确的有效结果:将eff_endt 更改为trunc(eff_endt)

这很好,但似乎没有必要进行更改。

openquery()应该是通过的,那么TOAD和openquery()的行为怎么会有区别呢?

我们关心的原因是因为我们经常使用 TOAD 直接访问 Oracle 来开发复杂的查询。一旦查询功能和优化后,我们将其转换为openquery() 字符串以在 SQL Server 应用程序中使用。当我们知道它作为直接查询工作时,查询突然以openquery() 失败是非常令人恼火的。然后我们必须通过反复试验寻找解决方法。

我想查看这两个场景的 Oracle 跟踪文件,但 Oracle 服务器在另一个组织内,我们没有得到 Oracle DBA 的合作。

有谁知道任何驱动程序、TOAD 或 ???可能导致差异的问题?有什么办法可以消除这个问题,让这两种方法总是给出相同的结果?

【问题讨论】:

    标签: tsql sql-server-2008-r2 oracle11g toad openquery


    【解决方案1】:

    我知道你前段时间问过这个问题,但我刚刚遇到了你的问题。

    我同意,它们应该是一样的。显然是有区别的。我们需要找出差异在哪里。

    我一边打字一边大声思考……

    如果您只指定几列而不是从 openquery 中选择 *,会发生什么情况?

    应该返回多少行?

    如果在 oracle 选择中限制了返回的行怎么办?

    openquery 超时有多快?

    TOAD 和 SS 在同一台机器上吗?您是否正在 RDP 进入 SS 并从那里运行 toad?

    他们是否使用相同的驱动程序?包括位? (32/64) 版本?

    他们在 oracle 上使用的是同一个帐户吗?

    有趣的是,使用trunc() 会有所不同。我假设 [eff_endt] 是返回的字段之一?

    我想知道 SS 是否正在恢复所有行,但它在进行日期转换时感到窒息。 oracle 中的日期类型可能需要先转换为 ss 日期类型,然后 ss 才会显示给您。

    如果您将 openquery 中的行插入到日期字段只是 (n)varchar 的表中,该怎么办。我在想 ss 可能只是将它从 oracle 返回的日期转储到该文本字段中而不尝试转换它。

    类似:

    insert into mytable(f1,f2,f3,datetimeX)
    select f1,f2,f3,datetimeX from openquery( servername, '
      select f1,f2,f3,datetimeX from ... where ...
      and srvg_ocd in (
        select ocd
         from rptofc
        where eff_endt = to_date(''12/31/9999'',''mm/dd/yyyy'')
          and rgn_nm = ''Boston''
      ) ...
    ');
    

    如果 toad 或 ss 在将查询语句发送到 oracle 之前对其进行了修改怎么办。你可以启动 wireshark 看看 toad 和 ss 实际发送了什么。

    如果你能解决这个问题,我会很好奇。我经常将 ss 链接到 oracle 并没有遇到这个问题。

    【讨论】:

    • 我们已经在 SS 端进行了跟踪 - 正在发送正确的查询,但 Oracle 没有返回任何内容。不同的 Oracle 帐户,但我不明白如果添加 trunc“修复”问题,这将如何解释差异。结果集非常小,没有任何日期或时间戳。 Openquery 没有超时——用户厌倦了等待并中止。 TOAD 和 SS 位于不同的机器上,具有不同的驱动程序。我们怀疑驱动程序,但我正在寻找有关已知问题的具体信息。我会看看我们是否可以访问诸如wireshark之​​类的东西。
    • 我刚刚发现我们的工作场所禁止使用网络流量嗅探器,所以我们没有使用wireshark。我们的敏感数据太多了。
    • 所以听起来他们没有加密他们的敏感数据。好吧,这是一个不同的讨论话题。我会看看能否在我的网站上重现您的问题。
    • 我无法重现您的问题。 eff_endt 是日期字段吗?什么样的日期字段?我想知道 toad 是否正在为您做出假设并进行更改,但 sql 只是发送原始查询。由于它是原始查询并且日期转换存在问题,因此某些东西要么中断,要么转换时间太长。我仍然会好奇电线上发生了什么。看看您是否可以让网络人员为您收集数据。
    • 这是一个 DATE,表示没有时间的日期,因此按照惯例,存储的值总是被截断为午夜。过去,我使用 SQL*Plus 成功地对该列运行了许多查询,而无需 TRUNC。条件的双方都是 DATE,因此不应该存在转换问题。我想知道是否存在一些奇怪的字符集问题,但我无法理解它是如何影响它的。
    【解决方案2】:

    您可以检查以下基本内容,以了解数据库在收到查询后正在执行的操作。首先,检查 TOAD 中的执行计划是否与使用 openquery 运行查询时相同。您可以使用以下方法在 TOAD 中自己计划查询:

    explain plan set statement_id = 'openquery_test' for <your query here>;
    
    select *
    from table(dbms_xplan.display(statement_id => 'openquery_test';
    

    然后让某人使用 openquery() 启动查询并让某人有权查看 v$ 表以运行:

    select sql_id from v$session where username = '<user running the query>';
    

    (如果与同一用户有多个连接,则必须找到一个附加属性来隔离表示运行查询的会话的行。)

    select *
    from table(dbms_xplan.display_cursor('<value from query above'));
    

    如果它们看起来相同,那么我会继续检查数据库等待,看看它卡在什么地方。

    select se.username
         , sw.event
         , sw.p1text
         , sw.p2text
         , sw.p3text
         , sw.wait_time_micro/1000000 as seconds_in_wait
         , sw.state
         , sw.time_since_last_wait_micro/1000000 as seconds_since_last_wait
      from v$session se
           inner join
           v$session_wait sw
              on se.sid = sw.sid
     where se.username = '<user running the query>'
    

    ;

    (同样,如果有多个会话使用相同的用户名,您将需要另一个属性将其缩减为您感兴趣的会话。)

    如果计划不同,那么您需要找出原因,或者如果它们相同,请查看它在等待什么(例如,向客户端发送 SQL*Net 消息?)以及原因。

    【讨论】:

      【解决方案3】:

      我注意到通过 MS Access (2013) 使用 OLEDB 连接到 Oracle 10g 和 11g 表的不同之处在于,它并不总是能正确识别 Oracle 表上的索引或主键。通过 MS Access 2000 数据库(使用 odbc)进行的相同查询工作正常/索引和键没有问题。我发现修复 OLEDB 版本的唯一方法是在 SELECT 中包含所有关键字段——这不是一个令人满意的答案,但这是我能找到的全部。这也可能是尝试通过 SSMS / OpenQuery(...) 的一个选项。

      除此之外...您可以尝试一些 OPENQUERY 的替代方案,例如:

      • 4 部分名称:SELECT ... FROM Server..Schema.Table
      • 在链接服务器上执行 AT: EXEC ('select...')

      但至于为什么 OLEDB 提供程序与原生 Oracle 提供程序的工作方式不同 - 提供程序并不相同,并且原生提供程序比更通用的 OLEDB 提供程序更有可能掩盖 Oracle 的怪癖。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-03
        • 1970-01-01
        • 2020-10-17
        • 1970-01-01
        • 2021-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多