Sql DB驱动程序返回结果的dict(Python、Perl等)或关联数组(PHP)。如果按名称而不是数组中的索引引用列,则代码更容易理解。

Sql DB驱动程序返回结果的dict(Python、Perl等)或关联数组(PHP)。如果按名称而不是数组中的索引引用列,则代码更容易理解。,sql,view,Sql,View,这些其他答案都有优点,但在SQL server上至少也有一些错误之处。试试这个: create table temp (i int, j int) go create view vtemp as select * from temp go insert temp select 1, 1 go alter table temp add k int go insert temp select 1, 1, 1 go select * from vtemp SQL Server在添加“新建”列时不会了

这些其他答案都有优点,但在SQL server上至少也有一些错误之处。试试这个:

create table temp (i int, j int)
go
create view vtemp as select * from temp
go
insert temp select 1, 1
go
alter table temp add k int
go
insert temp select 1, 1, 1
go
select * from vtemp
SQL Server在添加“新建”列时不会了解该列。取决于你想要什么,这可能是一件好事,也可能是一件坏事,但不管怎样,依赖它可能都不是好事。所以避免它似乎是个好主意

对我来说,这种奇怪的行为是避免在视图中选择select*的最有力的理由


这些评论告诉我MySQL有类似的行为,而Oracle没有(它将了解表的更改)。在我看来,这种不一致性是不在视图中使用select*的更多原因。

似乎没有其他人提到过它,但在SQL Server中,您也可以使用该属性设置视图

这可以防止对任何基表的修改(包括删除它们)影响视图定义


在某些情况下,这可能对您有用。我意识到我没有完全回答你的问题,但我想我还是要强调一下。

SQL查询基本上是由程序员设计的功能单元,用于某些上下文。为了实现长期稳定性和可支持性(可能由除您以外的其他人提供),功能单元中的所有内容都应该有特定的用途,并且应该合理明确(或记录)其存在的原因,尤其是数据的每个元素


如果两年后我带着改变你的问题的需要或愿望来到这里,我希望在我确信我能搞乱它之前,我会彻底地摸索它。这意味着我需要理解为什么所有的列都被调出。(如果您试图在多个上下文中重用查询,这一点更为明显。出于类似的原因,这通常是有问题的。)如果我在输出中看到与某些目的无关的列,我很肯定我不理解它做了什么,以及为什么,如果使用select*自动进行联接,则表示在联接字段中重复数据时,返回的数据多于所需的数据。这是对数据库和网络资源的浪费


如果您天真地使用调用其他视图的视图,那么使用select*会使它们的性能更差(这种技术本身对性能不利,调用不需要的多个列会使性能更差).

SQL Server上的情况实际上比@user12861的答案所暗示的还要糟糕:如果对多个表使用
SELECT*
,则向查询早期引用的表中添加列实际上会导致视图以旧列的名义返回新列的值。请参见下面的示例:

-- create two tables
CREATE TABLE temp1 (ColumnA INT, ColumnB DATE, ColumnC DECIMAL(2,1))
CREATE TABLE temp2 (ColumnX INT, ColumnY DATE, ColumnZ DECIMAL(2,1))
GO


-- populate with dummy data
INSERT INTO temp1 (ColumnA, ColumnB, ColumnC) VALUES (1, '1/1/1900', 0.5)
INSERT INTO temp2 (ColumnX, ColumnY, ColumnZ) VALUES (1, '1/1/1900', 0.5)
GO


-- create a view with a pair of SELECT * statements
CREATE VIEW vwtemp AS 
SELECT *
FROM temp1 INNER JOIN temp2 ON 1=1
GO


-- SELECT showing the columns properly assigned
SELECT * FROM vwTemp 
GO


-- add a few columns to the first table referenced in the SELECT 
ALTER TABLE temp1 ADD ColumnD varchar(1)
ALTER TABLE temp1 ADD ColumnE varchar(1)
ALTER TABLE temp1 ADD ColumnF varchar(1)
GO


-- populate those columns with dummy data
UPDATE temp1 SET ColumnD = 'D', ColumnE = 'E', ColumnF = 'F'
GO


-- notice that the original columns have the wrong data in them now, causing any datatype-specific queries (e.g., arithmetic, dateadd, etc.) to fail
SELECT *
FROM vwtemp
GO

-- clean up
DROP VIEW vwTemp
DROP TABLE temp2
DROP TABLE temp1

如果修改了字段的顺序,关联数组将继续工作。请阅读我的另一个答案,基础表中的更改并不总是反映出来,至少在SQL server上是如此。MySQL中的相同行为-新列不会成为视图的一部分。显然,在创建视图时,通配符被转换为列列表。同时重命名基表中的列也会使视图不可用。Oracle不是这样工作的。该视图将因表更改而无效,并在下次访问时使用新列重新编译。此外,使用该视图的代码不应使用*,因此在视图中使用*可能是非常合理的,使用该视图的代码有责任确保它没有使用*。最后的注释完全错误(至少在sql server中)-情况正好相反-对基础表的更改会被静默忽略。这是@user12861所提到的。在sql server中,任何使用select*的视图都需要在底列表更改时删除并重新创建,否则它将静默地不显示所有列。这是一种非常糟糕的失败形式,因为不太可能在在开发环境中,您将定期从头开始重建数据库。当您添加列时,也很容易忘记删除和重建表上的所有视图查看此链接以了解发生的详细情况这是我不使用SELECT*的主要原因。其他原因主要与您做其他危险的事情有关,例如,通过索引而不是名称来连接或引用列的SELECT*。嗯,这些当然是危险的组合。但SELECT*本身并不是邪恶的。我同意它通常并不危险。我在数据库上执行数据检查时经常使用SELECT*。但是,我在编写生产代码时倾向于避免使用SELECT*,以避免遇到上述问题,并继续实施良好的编程习惯。如果您以字典/关联数组/对象而不是使用数组索引访问行,则使用
*
的查询在基础表更改时同样健壮。字典/关联数组/对象可能比使用ar慢ray索引,但在许多情况下可读性胜过速度。我编写了大多数SQL查询作为
SELECT*
,并使用字典/关联数组/对象,除非可以证明某个特定代码存在性能问题。在大多数代码中,性能问题根本不存在。这只表明很难使用c将
*
-ed查询更改回显式命名查询;它没有说明
*
-ed查询不好的原因。在我看来,
*
-ed查询本身并没有什么不好的地方;它只是意味着不需要太细粒度。我不确定什么是“太细粒度”在依赖关系确定的上下文中表示。除非您已确定依赖关系不重要。
create table temp (i int, j int)
go
create view vtemp as select * from temp
go
insert temp select 1, 1
go
alter table temp add k int
go
insert temp select 1, 1, 1
go
select * from vtemp
-- create two tables
CREATE TABLE temp1 (ColumnA INT, ColumnB DATE, ColumnC DECIMAL(2,1))
CREATE TABLE temp2 (ColumnX INT, ColumnY DATE, ColumnZ DECIMAL(2,1))
GO


-- populate with dummy data
INSERT INTO temp1 (ColumnA, ColumnB, ColumnC) VALUES (1, '1/1/1900', 0.5)
INSERT INTO temp2 (ColumnX, ColumnY, ColumnZ) VALUES (1, '1/1/1900', 0.5)
GO


-- create a view with a pair of SELECT * statements
CREATE VIEW vwtemp AS 
SELECT *
FROM temp1 INNER JOIN temp2 ON 1=1
GO


-- SELECT showing the columns properly assigned
SELECT * FROM vwTemp 
GO


-- add a few columns to the first table referenced in the SELECT 
ALTER TABLE temp1 ADD ColumnD varchar(1)
ALTER TABLE temp1 ADD ColumnE varchar(1)
ALTER TABLE temp1 ADD ColumnF varchar(1)
GO


-- populate those columns with dummy data
UPDATE temp1 SET ColumnD = 'D', ColumnE = 'E', ColumnF = 'F'
GO


-- notice that the original columns have the wrong data in them now, causing any datatype-specific queries (e.g., arithmetic, dateadd, etc.) to fail
SELECT *
FROM vwtemp
GO

-- clean up
DROP VIEW vwTemp
DROP TABLE temp2
DROP TABLE temp1