【发布时间】:2011-07-08 10:31:03
【问题描述】:
考虑这个使用SELECT * 并“追加”计算列的查询:
SELECT *,
IIF(TRUE, 1, 0) AS calculated_col
FROM Orders;
我希望calculated_col 是结果集中最右边的一列。但是,它实际上是最左边的列。例如,在 SQL Server 中执行等效查询时,它位于最右边。
现在,因为这是 Access(ACE、Jet 等),SQL 标准不适用,而且 Access 帮助不会指定预期结果,因为它不够详细(礼貌地说)。所以我的问题是:
Access 总是以这种方式运行,还是我的环境(ADO、OLE DB 提供程序等)的“功能”?
Access 在给定的环境中是否总是以这种方式运行? (即为什么我以前没有注意到这一点?)
附:我当然知道SELECT * 被广泛嘲笑,如果列的顺序对我很重要,那么我应该明确地把它们都写出来。然而,我真的对遇到的实际行为感到惊讶,并对我的问题的任何答案感兴趣。
这里有一些 VBA 来重现该行为:只需复制+粘贴到任何 VBA 模块中,不需要设置引用并且不需要安装 Access,例如使用 Excel 的 VBA 编辑器:
Sub ColumnOrderWrong()
On Error Resume Next
Kill Environ$("temp") & "\DropMe.mdb"
On Error GoTo 0
Dim cat
Set cat = CreateObject("ADOX.Catalog")
With cat
.Create _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & _
Environ$("temp") & "\DropMe.mdb"
With .ActiveConnection
Dim Sql As String
Sql = _
"CREATE TABLE Orders" & vbCr & _
"(" & vbCr & " ID INTEGER, " & vbCr & _
" customer_id" & _
" INTEGER" & vbCr & _
");"
.Execute Sql
Sql = _
"INSERT INTO Orders (ID, customer_id) VALUES" & _
" (1, 2);"
.Execute Sql
Sql = _
"SELECT *, " & vbCr & _
" IIF(TRUE, 55, -99) AS calculated_col" & vbCr & _
" FROM Orders;"
Dim rs
Set rs = .Execute(Sql)
MsgBox _
"Fields(0).Name = " & rs.Fields(0).Name & vbCr & _
"Fields(1).Name = " & rs.Fields(1).Name & vbCr & _
"Fields(2).Name = " & rs.Fields(2).Name
End With
Set .ActiveConnection = Nothing
End With
End Sub
【问题讨论】:
-
为什么你会在没有表名的情况下使用 *?如果你写了糟糕的 SQL,你会得到不可靠的结果,所以不要写糟糕的(即模棱两可的)SQL。
-
在标准 SQL 中,结果是可预测且明确的。在 Access 中甚至没有定义结果,因此 Access IMO 是这里的“坏 SQL”。如果
FROM子句中只有一个表,为什么添加表名会对结果产生影响? -
SQL 标准中是否真的定义了列顺序?还是只是除了 Jet/ACE 之外的每个人都只是习惯性地使用 SELECT 的顺序来显示字段?我当然可以看出这是多么合乎逻辑,但除非 SQL 标准定义了它应该如何呈现,否则我认为你没有立足之地。
-
@David-W-Fenton:我相信 SQL-92 规范的第 7.9 节(语法规则 3 和 4)和 7.4(一般规则案例 1b)涵盖了它,但承认我不是100% 确定。
-
@David-W-Fenton:试试this。
标签: sql ms-access vba oledb ado