我正在做一个简单的查询:
fun main(args: Array<String>) {
Application.launch(HelloWorldApp::class.java, *args)
}
class HelloWorldApp : App(HelloWorld::class)
class HelloWorld : View() {
override val root = hbox {
addEventFilter(KeyEvent.ANY) { event ->
println("pressed:"+event.character)
}
}
}
按预期方式,返回了Bench表的所有行,但是如果我尝试获取B_id字段,我发现该字段已设置为NULL。 然后,我尝试了另一个应该完全等效的查询:
SELECT * FROM Bench LEFT JOIN ASSIGNED_DOM
ON (Bench.B_id=ASSIGNED_DOM.B_id) WHERE Bench.B_type=0 ;
但是在这种情况下,B_id字段会正确返回。 第一个查询出了什么问题?两者之间有什么区别?
答案 0 :(得分:1)
如果列名相同,则第二个表中的值将覆盖第一个表中的值。尝试在查询中使用别名
SELECT Bench.B_id AS bid1, ASSIGNED_DOM.B_id AS bid2
FROM Bench
LEFT JOIN ASSIGNED_DOM ON (Bench.B_id=ASSIGNED_DOM.B_id)
WHERE Bench.B_type=0;
答案 1 :(得分:1)
这两个查询不是等效的。根据{{3}}
自然联接和使用USING的联接,包括外部联接变体,均根据SQL:2003标准进行处理。
NATURAL联接的冗余列不出现。
这具体归结为以下差异:
USING子句可以重写为比较相应列的ON子句。但是,尽管USING和ON相似,但是它们并不完全相同。
关于确定哪些行满足连接条件,两个连接在语义上是相同的。
关于确定要为SELECT *扩展显示哪些列,两个联接在语义上并不相同。 USING联接选择相应列的合并值,而ON联接则选择所有表格中的所有列。
因此,您的第一个查询有两列同名bench.B_id, ASSIGNED_DOM.B_id
,而第二个查询只有一列coalesce(bench.B_id, ASSIGNED_DOM.B_id) as B_id
。
如何正确处理第一种情况取决于您的应用程序/框架。例如。 MySQL客户端或phpmyadmin将仅显示所有列。某些框架可能会以某种方式更改名称,以使其唯一。
特别是 php
(我假设您正在使用它)不会:如果使用$row['B_id']
,它将返回最后一次出现(尽管未指定行为),因此在情况下,您将得到ASSIGNED_DOM.B_id
。不过,您仍然可以访问两个具有索引的列(例如$row[0]
,$row[1]
),但只能访问具有相同列名的列中的一个。
为防止此类问题,您可以/应该使用别名,例如select bench.B_id as bench_B_id, ASSIGNED_DOM.B_id as ASSIGNED_DOM_B_id, ...
。