Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何选择*但不选择“;列名在每个视图中必须是唯一的;_Sql Server_Tsql_Select_View - Fatal编程技术网

Sql server 如何选择*但不选择“;列名在每个视图中必须是唯一的;

Sql server 如何选择*但不选择“;列名在每个视图中必须是唯一的;,sql-server,tsql,select,view,Sql Server,Tsql,Select,View,我需要封装一组我们经常在供应商的数据库服务器上使用的表联接。我们在摘录等中的许多地方重用了相同的连接逻辑,似乎视图允许在一个地方定义和维护连接 CREATE VIEW MasterView AS SELECT * FROM entity_1 e1 INNER JOIN entity_2 e2 ON e2.parent_id = entity_1.id INNER JOIN entity_3 e3 ON e3.parent_id = entity_2.id /* other joins inclu

我需要封装一组我们经常在供应商的数据库服务器上使用的表联接。我们在摘录等中的许多地方重用了相同的连接逻辑,似乎视图允许在一个地方定义和维护连接

CREATE VIEW MasterView
AS
SELECT *
FROM entity_1 e1
INNER JOIN entity_2 e2 ON e2.parent_id = entity_1.id
INNER JOIN entity_3 e3 ON e3.parent_id = entity_2.id
/* other joins including business logic */
etc.
问题是,供应商定期对数据库进行更改(列添加、名称更改),我希望这会自动反映在“MasterView”中

SELECT*允许这样做,但是基础表都有ID列,所以我得到了“每个视图中的列名必须是唯一的”错误

我特别希望避免从表中列出列名,因为a)它需要频繁维护b)每个表有几百列

是否有办法实现SELECT*的动态性,但有效地排除某些列(即ID列)


谢谢

生成所需列的一个简单方法是

select column_name+',' from information_schema.columns
where table_name='tt'
and column_name not in('ID')
我特别希望避免从表中列出列名,因为a)它需要频繁维护b)每个表有几百列

在这种情况下,你无法避免。必须指定列名,并且对于具有重复名称的列,请使用别名。代码生成可以帮助处理这些列

无论怎样,
SELECT*
都是不好的做法-如果有人向其中一个表中添加2GB二进制列并进行填充,您真的希望返回该列吗?

以及Oded的答案(100%同意)

如果有人更改了基础表,您仍然需要进行视图维护(使用sp_refreshview)。列更改不会自动出现在视图中。看

因此,您的“主视图”中反映的“自动”要求无论如何都不能得到满足


如果您想确保视图是最新的,请使用SCHEMABINDING,它将阻止对基础表的更改(直到删除或删除)。然后进行列更改,然后重新应用视图

我最后根据Madhivanan的建议进行了修改。这与t-clausen.dk后来的建议类似(感谢您的努力)尽管我发现xml路径样式比游标/列组分区更优雅

以下内容在运行时重新创建MasterView定义。基础表中的所有列都以表名开头,因此默认情况下,我可以在视图中包含两个名称类似的列。仅此一项就解决了我原来的问题,但我还包含了“WHERE column\u name NOT in in”“子句以明确排除某些永远不会在MasterView中使用的列

create procedure Utility_RefreshMasterView 
as
begin

    declare @entity_columns varchar(max)
    declare @drop_view_sql varchar(max)
    declare @alter_view_definition_sql varchar(max)

    /* create comma separated string of columns from underlying tables aliased to avoid name collisions */
    select @entity_columns = stuff((
        select ','+table_name+'.['+column_name+'] AS ['+table_name+'_'+column_name+']' 
        from information_schema.columns
        where table_name IN ('entity_1', 'entity_2')
        and column_name not in ('column to exclude 1', 'column to exclude 2')
        for xml path('')), 1, 1, '')


    set @drop_view_sql = 'if exists (select * from sys.views where object_id = object_id(N''[dbo].[MasterView]'')) drop view MasterView'

    set @alter_view_definition_sql = 
    'create view MasterView as select ' + @entity_columns + '
    from entity_1
    inner join entity_2 on entity_2 .id = entity_1.id
    /* other joins follow */'

    exec (@drop_view_sql)
    exec (@alter_view_definition_sql)

end

如果您有一个Select*,然后使用联接,则结果可能包含同名的列,而这在视图中是不可能的。如果您自己运行查询,则可以正常工作,但在创建视图时则不行

例如:

**Table A**
ID, CatalogName, CatalogDescription
**Table B**
ID, CatalogName, CatalogDescription
**After the JOIN query**
ID, CatalogName, CatalogDescription, ID, CatalogName, CatalogDescription
That's not possible in a View.

为视图中的每个列指定一个唯一的名称。仅使用*不是很好的做法。

我也有同样的问题,请参见下面的示例:

将视图摘要更改为
从表1中选择*作为t1
内部联接表2作为t1.Id=t2.Id上的t2

我遇到了您提到的错误,最简单的解决方案是使用
*
之前的别名,如下所示:

从表1中选择t1.*作为t1
内部联接表2作为t1.Id=t2.Id上的t2


您不应该再看到该错误。

是否尝试指定每个表?选择e1.*、e2.*等@ascanio-这不会有帮助,因为列名相同-结果集中可以有多个同名列。我对视图不太熟悉。您应该尝试我的解决方案,尽管它有0分,但效果很好。我完全同意y同意BP。但总的来说,可维护性的好处大于产生大量无用数据的可能性(在这种情况下,了解所涉及的数据类型是不可能的)@Ray:如果栏目发生变化,就不会有可维护性。请看我的答案。我只是在尝试一些可能性,使用这种悲伤,我制作了一个脚本来维护他的主视图。但我想他从来没有看到过。问题很快就解决了,其他人也没有看到过