例如,我有以下表格:
CREATE TABLE A (Id int, BId int, Number int)
CREATE TABLE B (Id int, Number decimal(10,2))
GO
INSERT INTO A VALUES(1, 3, 10)
INSERT INTO B VALUES(3, 50)
INSERT INTO A VALUES(2, 5, 20)
INSERT INTO B VALUES(5, 671.35)
GO
我多次运行以下查询:
SELECT * FROM A INNER JOIN B ON A.BId = B.Id
我应该得到类似的东西:
ID BId Number ID Number
1 3 10 3 50.00
2 5 20 5 671.35
但A.Number和B.Number是否可能处于不同的位置(在这方面也是ID)所以我会得到类似的东西:
ID Number ID BId Number
3 50.00 1 3 10
5 671.35 2 5 20
我们目前正在经历一些可能由此类造成的奇怪问题。我们有一个ASP.NET应用程序,执行一个基于自定义反射的代码生成数据映射器,它连接到SQL Server 2008集群。
我们发现有时会出现这样的错误:
'System.Decimal'类型的对象无法转换为'System.Int32'类型
试图弄清楚这是SQL Server中的行为,还是基于反射的数据映射器引擎中的行为。
正如您所看到的,两个表中的字段名称相同。想想也许当我们尝试做DataReader.GetValue(DataReader.GetOrdinal(“Number”))时,它将返回B.Number,它是一个小数而不是A.Number,它是一个int。
为了使问题进一步复杂化,这只会间歇性地发生(但只有在Web场中的特定IIS Web服务器上发生一次后才会一直发生)。
假设Web服务器A正常运行直到下午2点突然,我们收到此错误,我们将继续在Web服务器A上收到该错误,直到我们重置该服务器上的IIS,然后它就可以了。< / p>
有什么事可以做连接池以及SQL查询计划如何缓存?
答案 0 :(得分:1)
SQL是一种关系代数 - 如果您没有自己明确说明该命令,则该标准不会指定将返回哪些订单列。
我倾向于尽可能地避免使用"select *"
,因为它可能会堵塞网络中不必要的流量,并且更难以捕获列重命名和排序之类的内容,直到为时已晚。
只需选择您真正需要的列。
对于你的具体情况,我也只返回共享ID一次,因为你的连接必须是相同的(我倾向于选择“旧”的风格,因为DBMS应该足够聪明以优化它到内部无论如何加入):
select
a.Id as Id,
a.BId as BId,
a.Number as Number,
b.Number as BNumber
from
a, b
where
a.BId = b.Id
答案 1 :(得分:1)
只有交换表格订单时才可能出现第二种情况。
类似SELECT * FROM B INNER JOIN A ON A.BId = B.Id。
否则不可能。
答案 2 :(得分:1)
只有交换表格订单时才可能出现第二种情况。
连接顺序与列的位置无关,除非您使用不推荐的简单SELECT *。
即使在这种情况下,您也可以使用
SELECT B. ,A。,不改变联接顺序
最佳和推荐的解决方案是使用列名而不是*(在前两个答案中公布)
- 稍后补充
我忘记了一件我想指出的事情:对具有相同名称的列使用列别名,例如。
选择A.Number为NumberA,B.Number为NumberB
答案 3 :(得分:0)
我认为我没有看到它交换订单,但我个人不会在生产代码中使用“SELECT *
”:
SELECT A.[Id], A.[Bid], A.[Number], B.[Id], b.[Number]
FROM A INNER JOIN B ON A.[BId] = B.[Id]
或者最坏的情况:
SELECT A.*, B.* FROM A INNER JOIN B ON A.[BId] = B.[Id]