Select*和Select[列出每一列]之间有区别吗



我使用的是MS SQL Server 2005。对于SQL引擎来说,之间有区别吗

SELECT * FROM MyTable;

SELECT ColA, ColB, ColC FROM MyTable;

ColA、ColB和ColC何时表示表中的每一列?

如果它们是一样的,你有理由使用第二个吗?我有一个项目非常依赖LINQ,我不确定它生成的标准SELECT*是否是一种糟糕的做法,或者我是否应该一直是。在上面选择()以指定我想要的列。

编辑:为了清楚起见,将"当ColA、ColB和ColC都是表中的列时。

通常,最好是显式的,所以Select col1, col2 from Table更好。原因是,在某个时刻,可能会向该表中添加一个额外的列,并导致从查询中带回不需要的数据。

不过,这并不是一条硬性规定。

1)第二个更明确地说明返回哪些列。第二个的值是明确知道哪些列会返回的值。

2) 当列数多于显式使用的列数时,返回的数据可能会减少。

3) 如果通过添加新列来更改表,则第一个查询会更改,而第二个查询不会更改。如果您有类似"for all columns return do…"的代码,那么如果您使用第一个,而不是第二个,则结果会发生变化。

我会让很多人对我感到不安,但尤其是如果我稍后添加列,我通常喜欢使用SELECT*FROM表。出于这个原因,我被称为懒惰,因为如果我对我的表进行任何修改,我不想追踪所有使用该表的存储过程,只想在我的应用程序中的数据访问层类中更改它。在某些情况下,我会指定列,但在试图从数据库中获取完整的"对象"的情况下,宁愿只使用"*"。是的,我知道人们会因此讨厌我,但这让我在向应用程序添加字段时更快、更少地出现错误。

问题的两个方面是:随着新列的添加,显式列规范提供了更好的性能,但*规范在添加新列时不需要维护。

使用哪一个取决于您希望添加到表中的列的类型,以及查询的目的

如果您将表用作对象的后备存储(在LINQ to SQL的情况下似乎很可能),则可能希望添加到此表的任何新列都包含在对象中,反之亦然。你将它们保持平行。因此,在这种情况下,SELECT子句中的*规范是正确的。每次发生更改时,显式规范都会为您提供额外的维护,如果您没有正确更新字段列表,则会出现错误。

如果查询将返回大量记录,那么出于性能原因,最好使用显式规范。

如果这两件事都是真的,那么考虑使用两个不同的查询。

您应该指定一个显式列列表。SELECT*将带回比创建更多IO和网络流量所需更多的列,但更重要的是,即使存在非集群覆盖索引(在SQL Server上),它也可能需要额外的查找。

不使用第一条语句(选择*)的一些原因是:

  1. 如果稍后在该表中添加一些大字段(BLOB列会非常糟糕),则应用程序中可能会出现性能问题
  2. 如果查询是包含两个或多个表的JOIN查询,则某些字段可能具有相同的名称。最好确保您的字段名称不同
  3. 从编程美学的角度来看,第二条语句使查询的目的更加清晰

单独选择每个字段时,可以更清楚地看到实际选择的字段。

SELECT*在大多数地方都是一种糟糕的做法。

  • 如果有人在该表中添加了一个2gb BLOB列,该怎么办
  • 有人在表中添加了哪些列

这是一个等待发生的错误。

两件事:

  • 很多人在这里发帖建议不要使用*,并给出了几个很好的理由。到目前为止,在其他10个回复中,只有一个不建议列出列
  • 当人们在StackOverflow等帮助网站上发帖时,通常会对该规则进行例外处理,因为他们通常不知道表中的哪些列或对查询很重要。出于这个原因,你会在这里和网上其他地方看到很多使用*语法的代码,尽管发帖者倾向于在自己的代码中避免使用*语法

它有利于前向兼容性。

当你使用

SELECT * FROM myTable

在"myTable"中有3列。您得到的结果与相同

SELECT Column1, Column2, Column3 FROM myTable

但若你们在未来添加新的专栏,你们会得到不同的结果。

当然,若您更改现有列的名称之一,在第一种情况下会得到结果,在第二种情况下则会得到错误(我认为,这是应用程序的正确行为)。

如果您的代码依赖于某些列按特定顺序排列,则需要列出这些列。如果不是,那么在select语句中使用"*"或写出列名并没有什么区别。

例如,如果在表中插入一列。

拿这张桌子:ColA ColB ColC

你可能会有一个问题:

SELECT *
FROM myTable

那么代码可能是:

rs = executeSql("SELECT * FROM myTable")
while (rs.read())
    Print "Col A" + rs[0]
    Print "Col B" + rs[1]
    Print "Col C" + rs[2]

如果在ColB和ColC之间添加一列,查询将不会返回您要查找的内容。

对于LinqToSql,如果您计划稍后修改这些记录,则应该将整个记录拉入内存。

这取决于你所说的"差异"是什么意思。有明显的语法差异,但真正的差异在于性能。

当您说SELECT * FROM MyTable时,您是在告诉SQL查询引擎返回该表中所有列都的数据集,而SELECT ColA, ColB, ColC FROM MyTable告诉查询引擎返回表中仅ColA、ColB和ColC的数据集。

假设您有一个包含100列的表,定义为CHAR[10]。CCD_ 4将返回100列*10字节的数据,而CCD_。这是通过导线传回的数据量的巨大差异。

指定列列表也可以更清楚地显示您感兴趣的列。缺点是,如果您在表中添加/删除列,则需要确保列列表也得到更新,但我认为与性能提升相比,这只是一个小代价。

SELECT * FROM MyTable

select*取决于架构中的列顺序,因此如果引用集合的索引#所设置的结果,则会看到错误的列。

SELECT Col1,Col2,Col3 FROM MyTable

这个查询将为您提供一个随时间保持不变的集合,但是您多久更改一次列顺序?

快速查看查询执行计划可以发现查询是相同的。

一般的经验法则是,您希望将查询限制为只返回需要返回的字段。

选择每一列比只选择*要好,因为如果添加或删除新行,您必须查看代码并查看您对检索到的数据所做的操作
此外,它还可以帮助您更好地理解代码,并允许您使用别名作为列名(以防您与共享名称的列执行表的联接)

关于为什么永远不应该(imho)使用SELECT*的示例。这与MSSQL无关,而是MySQL。5.0.12之前的版本以非标准方式从某些类型的联接返回列。当然,如果您的查询定义了您想要的列以及顺序,那么就没有问题。想象一下,如果他们不这样做会有多有趣。

(一个可能的例外:您的查询仅从一个表中选择,并且您通过名称而不是位置来识别所选编程语言中的列。)

使用"SELECT*"优化了程序员的键入。就是这样,这是唯一的优势。

相关内容

最新更新