【问题标题】:SQL Query using two dates使用两个日期的 SQL 查询
【发布时间】:2020-09-05 03:57:55
【问题描述】:

当它包含单个日期时,我可以运行以下 SQL 查询。当我介绍第二个日期时,不会返回任何结果。

我也可以使用DD/MM/YY 格式进行此操作,但只有一个日期。

我正在使用 Office 2010 并连接到 Oracle SQL 数据库。

Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
Dim ConnectionString As String
Dim StrQuery As String
   
ConnectionString = SQLConnect 'This is a function that resolves to the connection string
cnn.Open ConnectionString
cnn.CommandTimeout = 180
    
StrQuery = "select  ref, date from records  where  date > '10-MAY-20'  And date < '13-MAY-20'"
    
rst.Open StrQuery, cnn
    
ThisWorkbook.Sheets("Sheet 1").Range("A2").CopyFromRecordset rst
rst.Close
cnn.Close

我尝试将查询修改为“选择noteno,从日期在'10-MAY-20'和'13-MAY-20'之间的记录中转换”。

当使用单个日期时,这两个查询都可以在 Oracle SQL Developer 中工作。

当通过 VBA 运行时,“选择 noteno,从日期如 '%MAY-20' 的记录中转换”也不起作用(但在 Oracle SQL 开发人员中很好)。

【问题讨论】:

  • 日期不能小于10-MAY-20,同时不能大于13-MAY-20,如果您需要介于两者之间的日期,请切换您的&lt;&gt; 符号。如果您的意思是所有不是之间的日期,那么您的And 必须是Or。 • 还要确保您的日期格式正确,您可能需要将其更改为2020-05-10(取决于您的设置,请检查)。
  • DATE 没有任何格式,它是特定于语言环境的NLS settings 具有以字符串显示日期的格式。 '10-MAY-20' 不是日期,而是字符串。您必须使用TO_DATE 将其转换为日期。或者,使用ANSI date literal。此外,停止使用 两位数 表示 year。这就是 Y2K 错误开始的全部原因。
  • @StewartLancaster 根据ISO 8601 只存在YYYY-MM-DD。这种日期格式是国际交流中唯一不能被误解的格式(xkcd.com/1179)。 YYYY-DD-MM 格式不存在另见stackoverflow.com/questions/2254014/…
  • 日期是Oracle中的保留字还是"date"
  • @StewartLancaster 也可以在下面查看 Lalit 的答案。他又解释了一些。

标签: sql excel vba oracle date


【解决方案1】:

其中日期 > '10-MAY-20' 和日期

'10-MAY-20' 不是日期,而是字符串。日期没有任何格式,根据特定于语言环境的 NLS 设置,它使用TO_CHAR 和正确的格式掩码以人类可读的格式显示。

此外,您应该避免使用两位数的 YY 表示年份,这是 Y2K 错误开始的全部原因。始终使用YYYY 格式。

将字符串转换为日期:

使用TO_DATE 和适当的格式掩码:

where  date_col > TO_DATE('10-MAY-2020', 'DD-MON-YYYY')  
and    date_col < TO_DATE('13-MAY-2020', 'DD-MON-YYYY')

或者,使用ANSI date literal,它使用固定格式'YYYY-MM-DD'

where  date_col > DATE '2020-05-10' and date < DATE '2020-05-13'

另外,DATE是Oracle的保留字,可以看documentation。也许,您正在使用 quoted identifier "date",即在保留字周围使用双引号。

我不明白为什么不使用“10-MAY-20”,因为这是 Oracle SQL 开发人员所需的格式

这可能是因为您的 SQL Developer 的 NLS 设置设置为 'DD-MON-YY',因此当您以该格式传递日期时,它不会隐式转换为日期。但是,如果您更改格式,它将不起作用:

alter session set NLS_DATE_FORMAT = 'YYYY-MM-DD';

【讨论】:

  • 如果您使用计算机,我会说一个普遍而重要的建议是:确保 您曾经使用的唯一日期格式YYYY-MM-DD,因为这是唯一的格式全世界都一样,连电脑都不能误解。如果您需要使用其他本地化格式,请仅用于显示目的。如果你遵循这条规则,你的生活会轻松很多。
  • @Pᴇʜ 好吧,事实上,Oracle 比 ISO 标准更早,这些 Oracle 特定语法存在。但是,建议使用全球公认的标准。
  • 嗯,没错。我应该更准确,应该说“只要有可能,切换到YYYY-MM-DD”:)
【解决方案2】:

日期不是字符串,如果您处理表示日期的字符串,则由驱动程序或数据库将其解释为日期。 Oracle 期望有一个TO_DATE-函数,对于 SQL 服务器,您可以在没有函数的情况下编写它 - 如果您使用正确的格式。对于其他数据库,可能会有所不同。

我一直提倡使用ADODB.Parameter 来传递参数。这意味着更多的代码,但参数格式(字符串、浮点数等也是如此)和防止 SQL 注入的保护不再有麻烦。您需要为传递给数据库的每个参数创建一个ADODB.Command 对象和一个ADODB.Parameter。在查询中,您只需将参数值替换为 ?

dim d1 as Date, d2 as Date    
d1 = CDate("2020-05-10")   ' Control of the date is completely in your hand.
d2 = CDate("2020-05-13")

StrQuery = "select  ref, date from records  where  date > ? And date < ?"
' Create command
Dim cmd as New ADODB.Command
Set cmd.ActiveConnection = cnn
cmd.CommandText = StrQuery 

' Create 2 parameter of type Date and pass the date values
Dim param as ADODB.Parameter
Set param = cmd.CreateParameter("p1", adDate, adParamInput, , d1)
cmd.Parameters.Append param
Set param = cmd.CreateParameter("p2", adDate, adParamInput, , d2)
cmd.Parameters.Append param

Set rst = cmd.Execute

【讨论】:

    猜你喜欢
    • 2018-07-25
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2011-07-04
    • 2010-12-14
    • 1970-01-01
    • 2015-04-01
    • 1970-01-01
    相关资源
    最近更新 更多