Access 2003 SQL Switch会破坏数据类型吗?

时间:2009-10-06 23:59:29

标签: sql ms-access ms-access-2003

我正在运行Access 2003.我正在使用Switch根据布尔标准选择日期字段:

Switch(<criterion>, Date1, 1, Date2)

即,如果“criterion”为true,则返回Date1,否则返回Date2。

Date1和Date2是表格中的日期/时间类型列。

问题是,Switch将它们作为文本返回 - 而不是日期/时间!

有没有办法强迫他们进入日期?我试过了

Switch(<criterion>, #Date1#, 1, #Date2#)

Switch(<criterion>, Val(Date1), 1, Val(Date2))

两者都失败并出现一条错误消息。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

我认为立即If [IIf()]函数更适合你想要做的事情:

IIf(<criterion>, Date1, Date2)

但Switch()函数不应该破坏数据类型,并且与日期/时间数据类型不兼容。考虑这个功能:

Public Function trySwitch(ByVal pWhichDay As String) As Variant
    Dim varOut As Variant
    varOut = Switch(pWhichDay = "yesterday", Date - 1, _
        pWhichDay = "today", Date, _
        pWhichDay = "tomorrow", Date + 1)
    trySwitch = varOut
End Function

trySwitch(“今天”)返回 10/6/2009 TypeName(trySwitch(“今天”))返回日期

答案 1 :(得分:1)

你的例子有些奇怪。

Switch接受表达式对,如果第一个计算结果为True,则返回其配对值,否则,它将传递给第二个,并计算该参数。

你似乎把1视为真,这是因为它不是Fales,但你会更好:

  Switch(<criterion>, Date1, True, Date2)

但这只是立即If函数的复制,IIf()和IIf()只需要较少的参数。

但它有同样的问题,因为它返回一个变体。但您应该能够将其强制转换为可以格式化为日期的数据类型。

但是,该变体是否会被隐式胁迫,或者您是否需要明确地执行它,取决于您使用它的位置。在查询结果中,您可以将IIf([criterion],Date1,Date2)的输出排序为日期,因为该列会被强制转换为日期类型。

如果必须显式执行强制,则CDate()是要使用的函数 - 您将使用CDate()函数包装生成Variant输出的外部函数,以确保变量输出是显式的被胁迫的日期类型:

  CDate(IIf(<criterion>, Date1, Date2))

但我很可能会错过这里重要的事情,因为我似乎在完全不同的轨道上......

答案 2 :(得分:1)

你能发布一些代码和数据来重现这个问题吗?因为这是SQL代码中的SWITCH(),所以我认为SQL DDL(CREATE TABLE等)和DML(INSERT INTO来添加数据)是最合适的:)

[挑剔点:Access数据库SQL没有'boolean'数据类型。它有一个YESNO数据类型,可以是NULL值;三值逻辑不是布尔值。]

这里有一些SQL DML(ANSI-92 Query Mode语法)来演示它如何按预期工作:

SELECT TYPENAME
       (
          SWITCH
          (
             NULL, #2009-01-01 00:00:00#, 
             FALSE, #2009-06-15 12:00:00#, 
             TRUE, #2009-12-31 23:59:59#
          )
       );

更改任何“标准”值,该值始终返回为“日期”,即DATETIME类型。


更新:

  

TYPENAME功能很棒   访问似乎解释了   结果集的整个“列”   不同

事实上。由于列只能是一种数据类型,因此行中TYPENAME()的结果可能会产生误导。必须将混合类型的行值“提升”为更高的数据类型。与访问数据库引擎一样,该过程完全不透明,并且关于主题的文档完全不存在,因此您只需要吮吸它并查看例如

SELECT #2009-01-01 00:00:00# AS row_value, 
       TYPENAME(#2009-01-01 00:00:00#) AS row_type
  FROM Customers
UNION ALL
SELECT 0.5, 
       TYPENAME(0.5) AS row_type
  FROM Customers

分别返回'Date'和'Decimal'但该列是什么?显然,答案是:

SELECT DT1.row_value, TYPENAME(DT1.row_value) AS column_type
  FROM (
        SELECT DISTINCT #2009-01-01 00:00:00# AS row_value 
          FROM Customers
        UNION ALL
        SELECT DISTINCT 0.5
          FROM Customers
       ) AS DT1;

'STRING'?!

...当然甚至不是Access数据库引擎SQL数据类型。所以TYPENAME()令人讨厌地使用了“最适合”的VBA类型的名称。例如:

SELECT TYPENAME(CBOOL(0));

返回'Boolean',尽管如上所述,Access Database Engine SQL中没有布尔数据类型。和

SELECT TYPENAME(my_binary_col)

返回'String'。请注意,相同的VBA映射限制适用于CAST函数(还有另一个烦恼),例如没有'强制转换为BINARY'函数,自Jet 4.0以来CDEC()函数仍然被破坏:(