• PowerShell应用之生成创建表的TransactSQL脚本


    开始


    在上一篇《PowerShell应用之-(SMO) 类库》,我们对SMO类库的应用有了基本的了解,在这里我们将继续对SMO类库进一步了解。在这篇,涉及这几个内容:

    • 表对象(Table)
    • 脚本选项(ScriptingOptions)
    • Sort-Object命令
    • Get-Date命令
    • Out-File命令

    下面我们着重描述表对象和脚本选项两个部分,其他部分写在后面的完整代码中。

    表对象(Table)


    要生成创建表的Transact-SQL脚本,先要找到着手点。在SMO类库中,Microsoft.SqlServer.Management.Smo.Table类中有两个方法,Script()和Script(ScriptingOptions)能为我们提供创建表的Transact-SQL脚本。如果我们要生成一个实例下的一个数据库里面所有表的脚本,我们要借助Microsoft.SqlServer.Management.Smo.Server类下的Databases属性,在Databases属性包含有数据库对象集合。我们接着可以在Databases对象集合中找到Tables属性,它包含有对应数据库的表对象(Table)集合.这一过程就是一层一层的往下检索对应的对象,犹如Tree列表,一层一层的往下搜。

    e.g.<代码01>

    <#===========================================#>
    $serverInstance="WINSERVER01\SQL2008DE01"
    $userName="sa"
    $password="sql20081"
    $DataBase="test"

    <#===========================================#>
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null

    $ServerConnection =new-object "Microsoft.SqlServer.Management.Common.ServerConnection" $serverInstance,$userName, $password

    Try
    {
    $ServerConnection.Connect()
    }
    Catch
    {
    Write-Error $_
    }

    if($ServerConnection.IsOpen)
    {
    #获得数据库中的用户表
    $Tables=((New-Object "Microsoft.SqlServer.Management.Smo.Server" $ServerConnection).databases[$DataBase]).tables | Where-Object -FilterScript{$_.IsSystemObject -eq $False}

    }

    我们在Windows PowerShell ISE上编写上面<代码01>。“获得数据库中用户表”的那行代码我们已作简化,要是一层一层的应用可以这样写:

    $Server=New-Object "Microsoft.SqlServer.Management.Smo.Server" $ServerConnection
    $DataBases=$Server.Databases
    $Tables=$DataBases.tables | Where-Object -FilterScript{$_.IsSystemObject -eq $False}

    在获取数据库中的用户表代码行中,应用到了Where-Object命令 把系统创建的表给过滤掉。在Table对象中的属性IsSystemObject就是描述是否是系统表。

    脚本选项(ScriptingOptions)


    前面我们提到Microsoft.SqlServer.Management.Smo.Table类中有两个方法,Script()和Script(ScriptingOptions)能生成创建表的脚本。Script()方法是最简单的方法,不过生成的脚本中不包含外键,主键等约束,也没有能生成索引。

    image

    为了能把脚本生成得更完整,我们这里调用第二种方法Script(ScriptingOptions),通过设置脚本选项(ScriptingOptions)来生成所需要的脚本。

    脚本选项,是ScriptingOptions对象,它对应的类是Microsoft.SqlServer.Management.Smo.ScriptingOptions类。ScriptingOptions对象能为我们提供丰富的对象脚本选项.

    e.g.

    #腳本选项设置
    $ScriptingOptions = New-Object "Microsoft.SqlServer.Management.Smo.ScriptingOptions"

    image

    通过命令“$ScriptingOptions | Get-Member”,可以查到到脚本选项包含的属性,也可以直接执行命令”$ScriptingOptions”查看当前的脚本选项,

    e.g.

    image

    image

    我们还可以通过设置$ScriptingOptions中的各个属性描述生成脚本的内容格式等。

    e.g.

    $ScriptingOptions.DriAllKeys         = $True
    $ScriptingOptions.DriClustered = $True
    $ScriptingOptions.DriAllConstraints = $True
    $ScriptingOptions.DriDefaults = $True
    $ScriptingOptions.DriIndexes = $True
    $ScriptingOptions.DriNonClustered = $True
    $ScriptingOptions.DriPrimaryKey = $True
    $ScriptingOptions.DriUniqueKeys = $True
    $ScriptingOptions.AnsiFile = $False
    $ScriptingOptions.ClusteredIndexes = $True
    $ScriptingOptions.IncludeHeaders = $False
    $ScriptingOptions.Indexes = $True
    $ScriptingOptions.SchemaQualify = $False
    $ScriptingOptions.Triggers = $True
    $ScriptingOptions.XmlIndexes = $True
    $ScriptingOptions.ExtendedProperties = $True
    $ScriptingOptions.NoFileGroup = $True
    $ScriptingOptions.NoCollation = $True
    $ScriptingOptions.IncludeIfNotExists = $True
    $ScriptingOptions.NoIdentities = $True

    可根据实际需要来设置,这里只是列出部分的内容及设置。

    e.g.生成脚本

    foreach($t in $Tables)
    {
    $t.Script($ScriptingOptions)
    }

    image

    考虑存在外键

    上面的生成脚本,执行后直接能在PowerShell控制台显示出来,但我们需要判断外键约束的时候,生成要有先后顺序,要把脚本保存为”.sql”格式文件,而且脚本文件名包含有生成的日期。

    为了能对于有外键的表需要注意生成顺序,我们引用了命令Sort-Object把表中的CreateDate和表ID进行排序即可。

    e.g.

    foreach($t in $Tables  | Sort-Object -Property CreateDate,ID)
    {
    $t.Script($ScriptingOptions)
    }

    CreateDate创建日期比较早的排序在前,当创建日期相同,再按表的ID升序排序,这样即可应付存在外键的情况。

    image

    完整的代码


    <#===========================================#>
    ##生成创建表的脚本,包含Constraints,Indexes,Triggers


    $serverInstance="WINSERVER01\SQL2008DE01"
    $userName="sa"
    $password="sql20081"
    $DataBase="ReplicationDB"
    $SrciptOutputPath="E:\"

    <#===========================================#>
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null

    $ServerConnection =new-object "Microsoft.SqlServer.Management.Common.ServerConnection" $serverInstance,$userName, $password

    Try
    {
    $ServerConnection.Connect()
    }
    Catch
    {
    Write-Error $_
    }

    if($ServerConnection.IsOpen)
    {
    #腳本选项设置
    $ScriptingOptions = New-Object "Microsoft.SqlServer.Management.Smo.ScriptingOptions"
    $ScriptingOptions.DriAllKeys = $True
    $ScriptingOptions.DriClustered = $True
    $ScriptingOptions.DriAllConstraints = $True
    $ScriptingOptions.DriDefaults = $True
    $ScriptingOptions.DriIndexes = $True
    $ScriptingOptions.DriNonClustered = $True
    $ScriptingOptions.DriPrimaryKey = $True
    $ScriptingOptions.DriUniqueKeys = $True
    $ScriptingOptions.AnsiFile = $False
    $ScriptingOptions.ClusteredIndexes = $True
    $ScriptingOptions.IncludeHeaders = $False
    $ScriptingOptions.Indexes = $True
    $ScriptingOptions.SchemaQualify = $False
    $ScriptingOptions.Triggers = $True
    $ScriptingOptions.XmlIndexes = $True
    $ScriptingOptions.ExtendedProperties = $True
    $ScriptingOptions.NoFileGroup = $True
    $ScriptingOptions.NoCollation = $True
    $ScriptingOptions.IncludeIfNotExists = $True
    $ScriptingOptions.NoIdentities = $True

    #获得数据库中的用户表
    $Tables=((New-Object "Microsoft.SqlServer.Management.Smo.Server" $ServerConnection).databases[$DataBase]).tables | Where-Object -FilterScript{$_.IsSystemObject -eq $False}

    if($Tables)
    {
    [System.Text.StringBuilder]$Sript="Use ["+$DataBase+"]`nGo`n"
    [int]$count=1

    #刪除腳本
    foreach($tb In $Tables | Sort-Object -Property CreateDate,ID -Descending)
    {
    $i=$Sript.AppendLine("If object_id('[" +$Tb.Name+ "]') Is Not null `n`t Drop Table ["+ $Tb.Name+ "]")
    }

    #创建脚本
    foreach($tb In $Tables | Sort-Object -Property CreateDate,ID)
    {
    foreach($s In $tb.Script($ScriptingOptions))
    {
    $i=$Sript.AppendLine($s)
    }
    Write-Host "處理完表 (" $count "/" $Tables.Count ")" ": " $tb.Name
    $count+=1
    }

    $i=$Sript.AppendLine("Go")

    #输出脚本
    [string]$Path=$SrciptOutputPath+$DataBase+"-"+(Get-Date -format yyyyMMdd)+".sql"
    $Sript.ToString() | Out-File -FilePath $Path
    }
    Else
    {
    Write-Error "无效的数据库: $DataBase 。或在数据库中找不到对应的表!"
    }

    }


    image

    小结


          上面描述了通过PowerShell 2.0生成创建表的Transact-SQL脚本,包含创建表,约束,外键,默认值,触发器和索引。可以根据自己实际的场景需要,修改部分的脚本选项。当然我在测试上面的脚本中,发现Table.Script(ScriptingOptions)方法生成脚本的方法比较慢,特别是一个数据库中包含有100以上的表,就感觉到缓慢,这方面有待优化提高。

  • 相关阅读:
    Python之图片格式转换
    pip依赖安装与记录
    Spectral Graph Theory的一些定理
    Beamer加中文
    Python之json
    Windows之建立C++开发环境
    Mysql分表教程
    null和空 not null
    yii 隐藏index.php的步骤
    yii泛域名
  • 原文地址:https://www.cnblogs.com/wghao/p/2235220.html
Copyright © 2020-2023  润新知