使用VIEW,表或视图的同义词是否有任何优点?

Ian*_*oyd -1 sql-server synonym sql-server-2008-r2

几十年来我一直用VIEWs作为同义词:

CREATE VIEW dbo.Banks AS

SELECT *
FROM OtherDatabase.dbo.Banks
Run Code Online (Sandbox Code Playgroud)

我这样做,所以我可以抽象"真正的"表格.当它发生变化时,就像改变视图一样简单:

这很好用.它不会导致优化器出现任何问题,并且我能够根据需要编辑视图.

在此输入图像描述

同义词

从SQL Server 2005开始,Microsoft引入了同义词:

CREATE SYNONYM dbo.Banks FOR OtherDatabase.dbo.Banks
Run Code Online (Sandbox Code Playgroud)

似乎工作相同VIEW方式.我看过的每个执行计划都表现得相同.

不幸的是,似乎同义词无法提供我们需要的基本功能之一:

提供一个抽象层,用于保护客户端应用程序免受对基础对象的名称或位置所做的更改

您无法更改同义词指向的位置.因为没有ALTER SYNONYM语句,所以首先必须删除同义词,然后重新创建具有相同名称的同义词,但将同义词指向新位置.

他们有任何兑换质量吗?

实际上,这不会发生.我永远不会这样做.我不会使用一种机制,要求我从数据库中删除对象以更改设置.我当然不是要删除所有容易改变的观点,与替换它们的同义词,而且还得给大家讲解为什么使一切困难是"更好".

所以我的问题是,使用视图我有什么损失吗?

  • 每个执行计划看起来都与同义词相同
  • 我可以很容易地改变"视图同义词"随时

我缺少的表或视图同义词是否有美德?

除了必须打电话RefreshAllViews以防万一我忘记了我在某个地方换了一张桌子

甚至存储过程

我甚至不使用存储过程的同义词:

CREATE PROCEDURE dbo.GetUSDNoonRateAsOf @tradeDate datetime AS

EXECUTE OtherDatabase.dbo.GetUSDNoonRateAsOf @tradeDate
Run Code Online (Sandbox Code Playgroud)

我失踪的同义词中是否有值?

更新:RefreshAllViews过程

我们在每个数据库中都有一个标准程序.重新排序或插入列会对视图造成严重破坏; 所以他们必须"刷新".

CREATE PROCEDURE [dbo].[RefreshAllViews] AS

-- This sp will refresh all views in the catalog. 
--     It enumerates all views, and runs sp_refreshview for each of them

SET NOCOUNT ON

DECLARE abc CURSOR FOR
     SELECT TABLE_NAME AS ViewName
     FROM INFORMATION_SCHEMA.VIEWS
     ORDER BY newid()
OPEN abc

DECLARE @ViewName varchar(128)
--DECLARE @ParmDefinition NVARCHAR(500)

-- Build select string once 
DECLARE @SQLString nvarchar(2048)
--SET @SQLString = N'EXECUTE sp_RefreshView @View'
--SET @ParmDefinition = N'@View nvarchar(128)'

FETCH NEXT FROM abc 
INTO @ViewName
WHILE @@FETCH_STATUS = 0 
BEGIN
    IF @ViewName <> 'IndexServerNodes'
    BEGIN
        SET @SQLString = 'EXECUTE sp_RefreshView '+@ViewName
        PRINT @SQLString
        EXECUTE sp_ExecuteSQL @SQLString--, @ParmDefinition, @View = @ViewName
    END

    FETCH NEXT FROM abc
    INTO @ViewName
END
CLOSE abc
DEALLOCATE abc
Run Code Online (Sandbox Code Playgroud)

天知道为什么SQL Server不会为我做这件事.

Aar*_*and 6

同义词是一种更加透明的重定向.我更喜欢它们而不是视图,因为需要维护视图.当你SELECT *特别使用时.

我不确定我是否认为缺乏ALTER SYNONYM真正的阻挡者.同义词的删除/创建是一个非常简单的元数据操作,并且速度非常快.省略错误处理以简化:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
  DROP SYNONYM ...
  CREATE SYNONYM ...
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)

同样,对于存储过程,如果基本存储过程接口发生更改(例如,添加参数),则还必须更改包装程序 - 而不是使用同义词.

一个缺点是你可以在视图上创建一个而不是触发器,但你不能在同义词上创建.您还无法通过同义词(主要是DDL)执行其他操作.当然,IntelliSense可能无法正常运行,具体取决于版本.

无法记住语法似乎是一个伪造的借口给我.没有花哨的选择或条款 ; 只是同义词的两部分名称,以及它所引用的对象的2部分,3部分或4部分名称:

CREATE SYNONYM dbo.Something FOR Server.Database.dbo.SomethingElse;
Run Code Online (Sandbox Code Playgroud)

如果你不能记住它,你是如何创建同义词的?

我还建议彻底简化您的存储过程(并防止它在dbo架构中没有任何视图时失败,或者该过程由默认架构与视图架构不同的人执行,或者视图具有'或其名称中的空格,或以其他方式违反标识符的任何规则(您可以在此页面上找到它们)):

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
Run Code Online (Sandbox Code Playgroud)

至少,如果您要保留光标,请停止使用可怕的默认选项(将光标声明为LOCAL FAST_FORWARD),然后使用sys.views而不是INFORMATION_SCHEMA.

天知道为什么SQL Server不会为我做这件事.

因为SQL Server是软件,并且它并不完美 - 特别是涉及到依赖项时.主要问题是您SELECT *首先在视图中使用违反最佳做法的行为.耸耸肩如果您接受关于同义词的挂钩,您将不必担心这一点.

  • 我完全同意.我从不运行SSMS生成的更改脚本.我要么使用通用帐户,要么等到找到无人值守的工作站,以便更改不会追溯到我 (5认同)
  • @IanBoyd懒惰不是不使用东西的真正原因.我也愿意打赌这会使你处于少数,因为大多数认真的SQL开发人员和DBA都会为重现能力编写脚本.如果我在我的部门中找到某人使用GUI来处理所有事情,我会非常生气,因为A)这是不安全的,B)需要更长的时间才能完成. (2认同)