几十年来,我一直使用VIEW
作为同义词:
CREATE VIEW dbo.Banks AS
SELECT *
FROM OtherDatabase.dbo.Banks
我这样做,所以我可以抽象出"真正的" 表所在的位置。当它改变时,它就像改变视图一样简单:
这很有效。它没有导致优化器出现任何问题,并且我能够根据需要编辑视图。
从SQL Server 2005开始,Microsoft引入了同义词:
CREATE SYNONYM dbo.Banks FOR OtherDatabase.dbo.Banks
似乎与<{1}}方法一起工作相同。我所看到的每个执行计划的行为都相同。
不幸的是,似乎同义词无法提供one of their basic functions, functionality i need:
提供一个抽象层,保护客户端应用程序免受对基础对象的名称或位置所做的更改
您无法更改同义词指向的位置。因为没有ALTER SYNONYM语句,所以首先必须删除同义词,然后重新创建具有相同名称的同义词,但将同义词指向新位置。
实际上,这不会发生。我永远不会这样做。我不会使用一种机制,要求我从数据库中删除对象以更改设置。我当然不会删除所有容易改变的 VIEW ,用 SYNONYM 替换它们,并且必须向每个人解释为什么让一切变得更难& #34;更好&#34;
所以我的问题是,使用视图我有什么损失吗?
我缺少的表或视图同义词是否有用?
除非必须致电
VIEW
以防忘记我在某处更换了桌子
我甚至不使用同义词来存储过程:
RefreshAllViews
我失踪的同义词中是否有值?
我们在每个数据库中都有一个标准程序。重新排序或插入列会对视图造成严重破坏;所以他们必须&#34;刷新&#34; 。
CREATE PROCEDURE dbo.GetUSDNoonRateAsOf @tradeDate datetime AS
EXECUTE OtherDatabase.dbo.GetUSDNoonRateAsOf @tradeDate
上帝知道为什么SQL Server不会为我做这件事。
答案 0 :(得分:6)
同义词是一种更加透明的重定向。我更喜欢它们而不是视图,因为需要维护视图。当你特别使用SELECT *
时。
我不确定我是否认为缺少ALTER SYNONYM
是一个真正的阻挡者。同义词的删除/创建是一个非常简单的元数据操作,并且速度非常快。为简洁省略错误处理:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
DROP SYNONYM ...
CREATE SYNONYM ...
COMMIT TRANSACTION;
类似地,对于存储过程,如果基本存储过程接口发生更改(例如,添加参数),则还必须更改包装程序 - 而不是同义词。
一个缺点是你可以在视图上创建一个而不是触发器,但你不能在同义词上创建。您还无法通过同义词(主要是DDL)执行其他操作。当然还有IntelliSense may not function correctly, depending on version。
无法记住语法似乎是一个伪造的借口。 There are no fancy options or with clauses;只是一个由2部分组成的同义词名称,以及它所引用的对象的2部分,3部分或4部分名称:
CREATE SYNONYM dbo.Something FOR Server.Database.dbo.SomethingElse;
如果您无法记住,那么您是如何创建同义词的呢?
我还建议彻底简化您的存储过程(并防止它在任何视图不在dbo
架构中时失败,或者该过程由默认架构与其不同的人执行视图的架构,或者视图名称中包含'
或空格,或以其他方式中断任何rules for identifiers (you can find them on this page)):
CREATE PROCEDURE [dbo].[RefreshAllViews]
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += '
EXEC sp_refreshview ' + CHAR(39)
+ QUOTENAME(REPLACE(s.name,'''',''''''))
+ '.' + QUOTENAME(REPLACE(v.name,'''','''''')) + CHAR(39) + ';'
FROM sys.views AS v
INNER JOIN sys.schemas AS s
ON v.[schema_id] = s.[schema_id];
PRINT @sql;
EXEC sp_executesql @sql;
END
GO
至少,如果您要保留光标,stop using the terrible default options (declare the cursor as LOCAL FAST_FORWARD
)和use sys.views
instead of INFORMATION_SCHEMA
。
天知道为什么SQL Server不会为我做这件事。
因为SQL Server是软件,it isn't perfect - especially when it comes to dependencies。主要问题是您使用SELECT *
in your views in the first place违反了最佳做法。 耸肩如果您接受关于同义词的挂断,您将不必担心这一点。
答案 1 :(得分:1)
如果视图引用了某个表,并且随后向该表添加了列,则必须修改该视图才能“选取”新列 - 即使您使用SELECT *
。同义词将自动“拾取”这些列。这是一个示例脚本:
-- Set things up
CREATE TABLE Foo
(
Id int not null
,data varchar(10) not null
)
GO
INSERT Foo values (1,'one'),(2,'Two')
GO
CREATE SYNONYM synFoo for Foo
GO
CREATE VIEW vFooDelim as select Id, Data from Foo
GO
CREATE VIEW vFooStar as select * from Foo
GO
select * from Foo
select * from synFoo
select * from vFooDelim
select * from vFooStar
然后,
-- Add a column
ALTER TABLE Foo
add MoreData datetime default getdate()
GO
select * from Foo
select * from synFoo
select * from vFooDelim
select * from vFooStar
GO
(别忘了)
-- Clean things up
DROP Synonym synFoo
DROP VIEW vFooDelim
DROP VIEW vFooStar
DROP TABLE Foo
一个更加模糊的情况(我们一直在这里做),如果你必须在数据库中为另一个数据库中的对象设置一个引用,你不一定知道该表中的列是什么(动态)是(或非常),并且您在编写代码时不知道数据库的名称(每个客户端一个数据库,但只有一旦签署合同)(通常),使用同义词可能是天赐之物。在创建数据库时,只需动态地构建并运行CREATE SYNONYM myTable FOR <DatabaseName>.<schema>.MyTable
,您就完成了 - 无论将来为哪个客户端添加哪些列。
答案 2 :(得分:0)
同义词适用于您处理大量不同数据源/多个数据库等或进行数据迁移的情况。
我从来没有真正找到理由在新的绿地开发中使用它们。