我如何编写所有模式绑定视图(以及阻止表截断的其他对象,如“过滤索引”)?

时间:2014-01-29 15:39:48

标签: sql-server sql-server-2012

我如何编写所有架构绑定视图的脚本?

P.S。父问题是模式绑定视图(以及筛选索引)破坏了SSMA(SQL SERVER迁移助手)数据导入,因为SSMA具有奇怪且不可配置的行为:在导入之前调用truncate table。参与模式绑定视图(索引视图)可防止表截断,其他此类对象:“过滤索引”。

2 个答案:

答案 0 :(得分:1)

使用SSMS功能生成脚本。在SSMS中,只需右键单击数据库,转到Task,然后转到Generate Script,它将为您提供选择,查看表格等选项。只需选择您想要的内容即可。

阅读此链接了解有关步骤的详细信息

http://technet.microsoft.com/en-us/library/hh245282.aspx

您可以将此用于从特定数据库获取所有视图的脚本,并仅使用特定模式

Use [MyDatabase]
SELECT o.name
       ,s.name
       ,OBJECT_DEFINITION(o.object_id) AS Create_script
    FROM sys.objects AS o
    JOIN sys.schemas AS s
        ON o.schema_id = s.schema_id
    WHERE type_desc = 'View'
    AND s.name = 'dbo' --Replace with your schema

更改只需从第3列中选择所有内容并粘贴到记事本++或您选择的其他工具中。只需将文件另存为.sql,您的脚本即可开始使用。

答案 1 :(得分:0)

SMO / powershell解决方案:

[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO')|Out-Null; 
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMOExtended')|Out-Null; 
$sr = '<server>'
$ln = '<login>'
$pw = '<password>'
$db = '<database>'

$u = 'Microsoft.SqlServer.Management.Smo'
$n = [Environment]::NewLine;
$s = new-object ($u+'.Server') $sr;
$c = $s.ConnectionContext;$c.LoginSecure=$false;$c.Login=$ln;$c.Password=$pw;
$s.SetDefaultInitFields((new-object ($u+'.View')).getType(), "IsSchemaBound");
$v=$s.Databases[$db].Views|Where-Object{$_.IsSchemaBound -eq $true}
if ($v | where $_.Triggers.Count -gt 0) {throw new-object System.ArgumentException 'Views with triggers are not supported'}
$_createScript = ('SET ARITHABORT ON','SET CONCAT_NULL_YIELDS_NULL ON','SET QUOTED_IDENTIFIER ON','SET ANSI_NULLS ON','SET ANSI_PADDING ON','SET ANSI_WARNINGS ON','SET NUMERIC_ROUNDABORT OFF')+
     ($v | %{$i=$_;(@()+'GO'+($i.Script()|where {$_ -notlike "SET * ON"})+'GO'+ ($i.Indexes|sort IsClustered –desc|%{$_.Script()}| where {$_ -notlike "SET *"}))})
$_dropScript =  $v | %{$_.Script(( new-object ($u+'.ScriptingOptions') -prop @{ScriptDrops =$true}))}
Write-Host (@()+'/*'+$_dropScript+'*/'+('-' * 40)+ $_createScript -join $n)

或者将相同的想法打包到T-SQL字符串中以便与xp_cmdshell一起使用。因此,您将获得新的存储过程 ManageObjectsThatPreventTruncate (名称可以在脚本“header”中配置)。检查它的内容(应该有脚本的所有视图和过滤索引)并以这种方式使用它:

ManageObjectsThatPreventTruncate(@drop=1) -- drop all indexed views and filtered indexes
ManageObjectsThatPreventTruncate() -- crate all indexed views and filtered indexes

ManageObjectsThatPreventTruncate(@drop=1, @schema='x') -- drop all indexed views and filtered indexes from schema X
ManageObjectsThatPreventTruncate(@schema='x') -- crate all indexed views and filtered indexes from schema X

ManageObjectsThatPreventTruncate(@drop=1, @schema='x', @name='y') -- drop concreate indexed view X.Y or drop all filtered indexes from table X.Y
ManageObjectsThatPreventTruncate(@schema='x', @name='y') -- crate concreate indexed view X,Y or drop all filtered indexes from table X.Y

ManageObjectsThatPreventTruncate(@drop=1, @schema='x', @name='y', @indexName='z') -- drop concreate filtered index X.Y
ManageObjectsThatPreventTruncate(@schema='x', @name='y', @indexName='z') -- crate concreate filtered index X.Y

脚本:

DECLARE @OUTPUT TABLE (id int identity(1,1), line nvarchar(max))
DECLARE @cmd VARCHAR(8000), @psAlterSP VARCHAR(8000),  @psGetDatabase VARCHAR(8000), @psGetViews VARCHAR(8000), @psGetFilteredIndexes VARCHAR(8000), @psLoadAssemblies VARCHAR(8000), @script nvarchar(max) ='',
    @psCompose1 VARCHAR(8000), @psCompose2 VARCHAR(8000), @psCompose3 VARCHAR(8000), @psCompose4 VARCHAR(8000), @psCompose5 VARCHAR(8000), @psComposeAll VARCHAR(8000)
DECLARE @sr nvarchar(max)='<server>', 
        @ln nvarchar(max)='<loginname>', 
        @pw nvarchar(max)='<password>', 
        @db nvarchar(max)=DB_NAME(),
        @sp sysname = 'ManageObjectsThatPreventTruncate',
        @ss sysname = 'dbo'
SET @psLoadAssemblies  = '[System.Reflection.Assembly]::LoadWithPartialName(''Microsoft.SqlServer.SMO'')|Out-Null;$ErrorActionPreference = ''Stop'';'
SET @psGetDatabase='$u =''Microsoft.SqlServer.Management.Smo'';$n = [Environment]::NewLine;$a = ''''+[char]39;$s = new-object ($u+''.Server'') $sr;$c = $s.ConnectionContext;$c.LoginSecure=$false;$c.Login=$ln;$c.Password=$pw;$s.SetDefaultInitFields((new-object ($u+''.View'')).getType(),''IsSchemaBound'');$d = $s.Databases[$db];'
SET @psGetDatabase=REPLACE(@psGetDatabase,'$sr',''''+@sr+'''')
SET @psGetDatabase=REPLACE(@psGetDatabase,'$ln',''''+@ln+'''')
SET @psGetDatabase=REPLACE(@psGetDatabase,'$pw',''''+@pw+'''')
SET @psGetDatabase=REPLACE(@psGetDatabase,'$db',''''+@db+'''')
SET @psGetViews = '$v=$d.Views|where {$_.IsSchemaBound -eq $true};if ($v | where {$_.Triggers.Count -gt 0}) {throw new-object System.ArgumentException ''Views with triggers are not supported''};'
SET @psGetFilteredIndexes = '$r = $d.ExecuteWithResults(''SELECT object_id, Name FROM sys.indexes WHERE has_filter=1 ORDER BY object_id, Name'');$x = @();foreach ($i in $r.Tables[0].Rows) {$x+=$d.Tables.ItemById($i[0]).Indexes[$i[1]]};'
SET @psCompose1='$o1=(''BEGIN TRY'',''IF @drop=1'',''BEGIN'')+($v | %{$_s=$_.Schema;$_n=$_.Name; \"IF (@schema is null or @schema=''$_s'') and (@name is null or @name=''$_n'') DROP VIEW [$_s].[$_n]\"})+($x | %{$_s=$_.Parent.Schema;$_tn=$_.Parent.Name;$_in=$_.Name; \"IF (@schema is null or @schema=''$_s'') and (@name is null or @name=''$_tn'') and (@indexName is null or @indexName=''$_in'') DROP INDEX [$_in] ON [$_s].[$_tn]\"})+''END'';'
SET @psCompose2='$o2=(''ELSE'',''BEGIN'',''SET ARITHABORT ON'',''SET CONCAT_NULL_YIELDS_NULL ON'',''SET QUOTED_IDENTIFIER ON'',''SET ANSI_NULLS ON'',''SET ANSI_PADDING ON'',''SET ANSI_WARNINGS ON'',''SET NUMERIC_ROUNDABORT OFF'',''DECLARE @sql varchar(max)'');'
SET @psCompose3='$o3= ($v | %{$i=$_;$_s=$_.Schema;$_n=$_.Name; (@()+(\"IF (@schema is null or @schema=''$_s'') and (@name is null or @name=''$_n'')\")+''BEGIN''+(''SET @sql =''+$a+(($i.Script()|where {$_ -notlike ''SET * ON''}) -join '''').Replace($a,$a+$a)+$a)  +''exec (@sql)''+( $i.Indexes| sort IsClustered –desc| %{ @()+$n+(''SET @sql =''+$a+(($_.Script()| where {$_ -notlike ''SET *''}) -join '''').Replace($a,$a+$a) +$a) +''exec (@sql)''})+''END'' )});'
SET @psCompose4='$o4= ($x | %{$i=$_;$_s=$_.Parent.Schema;$_tn=$_.Parent.Name;$_in=$_.Name;(@()+(\"IF (@schema is null or @schema=''$_s'') and (@name is null or @name=''$_tn'') and (@indexName is null or @indexName=''$_in'')\")+''BEGIN''+(''SET @sql =''+$a+(($i.Script()|where {$_ -notlike ''SET * ON''}) -join '''').Replace($a,$a+$a)+$a)+''exec (@sql)''+''END'')});'
SET @psCompose5='$o5=(''END'',''END TRY'',''BEGIN CATCH'',''THROW'',''END CATCH'');'
SET @psComposeAll= '$o=($o1+$o2+$o3+$o4+$o5) -join $n;'

SET @psAlterSP = '$p = $d.StoredProcedures[\"$sp\",\"$ss\"]; if($p -eq $null){$p = new-object ($u+''.StoredProcedure'') $d, \"$sp\",\"$ss\";$p.TextHeader=\"CREATE PROCEDURE [$ss].[$sp]$n @drop bit = 0,$n @schema sysname = NULL,$n @name sysname = NULL,$n @indexName sysname=NULL $n AS$n\";$p.TextBody=$o;$p.Create()}else{$p[0].TextBody=$o; $p[0].Alter()}'
SET @psAlterSP=REPLACE(@psAlterSP,'$sp',@sp)
SET @psAlterSP=REPLACE(@psAlterSP,'$ss',@ss)

SET @cmd = 'powershell -Command "'+@psLoadAssemblies+@psGetDatabase+@psGetViews+@psGetFilteredIndexes+@psCompose1+@psCompose2+@psCompose3+@psCompose4++@psCompose5+@psComposeAll+@psAlterSP+'"'
PRINT LEN(@cmd)
DECLARE @result int
INSERT INTO @OUTPUT (line)
exec @result =xp_cmdshell @cmd

IF @result=0 AND (SELECT count(*) FROM @OUTPUT WHERE line is not null)=0
BEGIN
    PRINT 'OK'
END
ELSE
BEGIN
    PRINT 'FAILURE'
    SELECT @script+line FROM @OUTPUT
    WHERE line is not null
    ORDER BY id;
    THROW 50000,'Error during xp_cmdshell execution',1;
END