Oracle 查询在 SQL 中工作但在 VB.NET 中不返回任何行

发布于 2024-12-11 17:58:05 字数 859 浏览 0 评论 0原文

帮忙,有什么想法吗?

我正在将 OLEDB 适配器 (Oracle OLEDB) 与 Oracle 10.2.0.3.0 结合使用。我的代码生成查询的 SQL,然后当我将其执行到 OLEDBDataReader 中时,HasRows 为 False。但是,如果我输出查询字符串的内容,复制并粘贴到 SQL+(以同一用户身份从同一客户端计算机登录),它将返回 993 行。什么给?

这是我的代码片段:

Dim DB As New OleDb.OleDbConnection(String.Format("{0};Password={1}", ConnectionString, DBPassword))
Dim flowQuerySQL As String
'... code to generate query
Debug.Print(flowQuerySQL)
Dim flowQueryCMD As New OleDb.OleDbCommand(flowQuerySQL, DB)
Dim flowQuery As OleDb.OleDbDataReader = flowQueryCMD.ExecuteReader()
While flowQuery.HasRows
    '...handle rows
End While

debug.print 语句显示:

SELECT CLASS_ID, OBJECT_ID FROM TDM_SF_PROCESS WHERE CLASS_ID=853 AND TDM_END_TIME >= '01-Jan-2009' AND TDM_END_TIME < '31-May-2009' AND TDM_STATUS <> 1 AND TDM_STATUS <> 2

Help, any ideas??

I am using the OLEDB adapter (Oracle OLEDB) with Oracle 10.2.0.3.0. My code generates the SQL for the query, then when I execute it into an OLEDBDataReader, the HasRows is False. However, if I output the contents of the query string, copy, and paste into SQL+ (logged in as the same user from the same client machine), it returns 993 rows. What gives??

Here's a segment of my code:

Dim DB As New OleDb.OleDbConnection(String.Format("{0};Password={1}", ConnectionString, DBPassword))
Dim flowQuerySQL As String
'... code to generate query
Debug.Print(flowQuerySQL)
Dim flowQueryCMD As New OleDb.OleDbCommand(flowQuerySQL, DB)
Dim flowQuery As OleDb.OleDbDataReader = flowQueryCMD.ExecuteReader()
While flowQuery.HasRows
    '...handle rows
End While

The debug.print statement shows:

SELECT CLASS_ID, OBJECT_ID FROM TDM_SF_PROCESS WHERE CLASS_ID=853 AND TDM_END_TIME >= '01-Jan-2009' AND TDM_END_TIME < '31-May-2009' AND TDM_STATUS <> 1 AND TDM_STATUS <> 2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

疯到世界奔溃 2024-12-18 17:58:05

我最近刚刚开始使用 VB.NET 来对抗 Oracle,并且日期不稳定。

到目前为止,这种方法对我来说一直有效:

SELECT CLASS_ID, OBJECT_ID 
FROM TDM_SF_PROCESS 
WHERE CLASS_ID=853 
  AND TDM_END_TIME >= TO_DATE('01-Jan-2009', 'DD-Mon-YYYY') 
  AND TDM_END_TIME < TO_DATE('31-May-2009', 'DD-Mon-YYYY') 
  AND TDM_STATUS <> 1 
  AND TDM_STATUS <> 2 

直到我使用“TO_DATE”函数之前它才起作用。希望这对你也有用。

我是一名 MS-SQL 专家,所以我还无法研究它为何有效的“原因”。启蒙,有人吗?

I have just recently started working VB.NET against Oracle, and dates are tempermental.

This approach has worked for me so far:

SELECT CLASS_ID, OBJECT_ID 
FROM TDM_SF_PROCESS 
WHERE CLASS_ID=853 
  AND TDM_END_TIME >= TO_DATE('01-Jan-2009', 'DD-Mon-YYYY') 
  AND TDM_END_TIME < TO_DATE('31-May-2009', 'DD-Mon-YYYY') 
  AND TDM_STATUS <> 1 
  AND TDM_STATUS <> 2 

It wouldn't work until I used the "TO_DATE" function. Hopefully this will work for you, too.

I'm a MS-SQL guy, so I haven't been able to research the "why" of why this works, yet. Enlightenment, anyone?

撩发小公举 2024-12-18 17:58:05

1) 您是否正在构建不使用绑定变量的查询?或者您是否为我们手动填写调试输出中的绑定变量?如果您不使用绑定变量,那么您实际上会在数据库中产生巨大的性能问题,因为您将破坏 Oracle 的共享池。您将创建容易受到 SQL 注入攻击的不安全代码。您最终将花费大量时间处理与数据类型、转义字符串等相关的问题。

如果您使用绑定变量,您只需在 VB.Net 应用程序中创建本地日期变量,将它们绑定到您的查询,通常一切都会正常。这会更加高效,因为 Oracle 只需要对语句进行一次硬解析,并且当您使用不同的日期一次又一次运行查询时,不会用类似的语句淹没共享池。

我不是 VB 开发人员。但是如果您使用绑定变量,您将用占位符替换 SQL 语句中的文字,即

AND TDM_END_TIME >= :early_time 
AND TDM_END_TIME <  :late_time 
AND TDM_STATUS <> :status_1 
AND TDM_STATUS <> :status_2

您将在运行时为这些绑定变量提供值,即

flowQueryCMD.Parameters.Add( ":early_time", <<your VB date object>> )
flowQueryCMD.Parameters.Add( ":late_time", <<your VB date object>> )

最后执行查询

2) 如果您不使用绑定变量,那么您必须确保您的数据类型匹配。 '01-Jan-2009' 是一个字符串,而不是日期,因此 Oracle 必须将该字符串隐式转换为日期。它通过使用会话的 NLS_DATE_FORMAT 来完成此操作。如果您的 NLS_DATE_FORMAT 碰巧不是“DD-MON-YYYY”,则转换将会失败(或默默地执行一些意外操作),并且您将不会获得预期的结果。由于每个会话的 NLS_DATE_FORMAT 可能不同,因此您永远不想依赖在任何特定会话中设置的任何特定 NLS_DATE_FORMAT,否则您的代码可能对您有用,但对您来说可能会失败碰巧更喜欢欧洲日期格式的同事。您的代码可能在一个会话(例如,SQL*Plus,即从一个位置获取其 NLS_DATE_FORMAT)中正常工作,但在另一会话(例如,获取其语言、字符集的 .Net 应用程序)中可能无法正常工作,以及来自 .Net 堆栈的日期格式设置)

在 Oracle 中有多种方法可以指定日期文字。第一个是使用 ANSI 日期文字(或时间戳文字)语法(请注意,ANSI 日期文字始终指定为 YYYY-MM-DD)

AND tdm_end_time >= date '2009-01-01'
AND tdm_end_time <  date '2009-05-31'

第二个选项是使用 TO_DATE 自己进行显式转换> 功能

AND tdm_end_time >= to_date( '01-Jan-2009', 'DD-MON-YYYY' )
AND tdm_end_time <  to_date( '31-May-2009', 'DD-MON-YYYY' )

1) Are you building a query that does not use bind variables? Or are you manually filling in the bind variables in your debug output for us? If you are not using bind variables, you're realistically going to create a massive performance problem in your database because you're going to crush Oracle's shared pool. You're going to create insecure code that is vulnerable to SQL injection attacks. And you are going to end up spending a lot of time dealing with gotchas relating to data types, escaping strings, etc..

If you were using bind variables, you would simply create local date variables in your VB.Net application, bind them to your query, and everything would generally work. This would be much more efficient since Oracle would only need to do a hard parse on the statement once and wouldn't flood the shared pool with similar statements when you run the query again and again with different dates.

I am by not a VB developer. But if you're using bind variables, you would replace the literals in your SQL statement with placeholders, i.e.

AND TDM_END_TIME >= :early_time 
AND TDM_END_TIME <  :late_time 
AND TDM_STATUS <> :status_1 
AND TDM_STATUS <> :status_2

You would then provide values for those bind variables at runtime, i.e.

flowQueryCMD.Parameters.Add( ":early_time", <<your VB date object>> )
flowQueryCMD.Parameters.Add( ":late_time", <<your VB date object>> )

Finally, you execute the query

2) If you are not using bind variables, then you have to make sure that your data types match. '01-Jan-2009' is a string, not a date, so Oracle has to implicitly convert the string to a date. It does this by using the session's NLS_DATE_FORMAT. If your NLS_DATE_FORMAT happens not to be 'DD-MON-YYYY', the conversion will fail (or silently do something unexpected) and you won't get the results you expect. Since the NLS_DATE_FORMAT can be different for every session, you never want to rely on any particular NLS_DATE_FORMAT being set in any particular session otherwise your code may work for you and fail for your colleague who happens to prefer European date formats. Your code may work fine in one session (say, SQL*Plus, that is getting its NLS_DATE_FORMAT from one place) and not in another session (say, a .Net application that gets it's language, character set, and date format settings from the .Net stack)

There are a couple of ways to specify date literals in Oracle. The first is to use the ANSI date literal (or timestamp literal) syntax (note that ANSI date literals are always specified as YYYY-MM-DD)

AND tdm_end_time >= date '2009-01-01'
AND tdm_end_time <  date '2009-05-31'

The second option is to do an explicit conversion yourself using the TO_DATE funciton

AND tdm_end_time >= to_date( '01-Jan-2009', 'DD-MON-YYYY' )
AND tdm_end_time <  to_date( '31-May-2009', 'DD-MON-YYYY' )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文