【问题标题】:Cloning an SQL Server 2008 Database Schema to a new Database - Programatically (PHP?)将 SQL Server 2008 数据库架构克隆到新数据库 - 以编程方式(PHP?)
【发布时间】:2011-11-04 15:15:36
【问题描述】:

我在 SO 上进行了一些谷歌搜索和搜索,但在这件事上我找不到太多帮助。我正在设计一个使用 Microsoft SQL Server 2008 Server 的 Web 服务。相关结构是这样的......有一个主数据库,其中包含所有主要帐户/公司信息(公司名称,地址等)。此外,每个帐户/公司都有一个数据库,其中包含该帐户的所有相关(元?)数据(用户、设置等...)。

SQL2008 Server
|---MainDatabase
|-------Accounts Table
|-----------Account Record where ID = 1
|-----------Account Record where ID = 2
|-----------Account Record where ID = 3
|---AccountDatabase00001
|-------Users Table for account where ID = 1
|---AccountDatabase00001
|-------Users Table for account where ID = 2

当创建一个新帐户时(假设 ID=3),我试图找出一种方法将 AccountDatabase0001 的表架构和视图(不是数据)克隆到一个名为 AccountDatabase00003 的新数据库中.只要能以某种方式从 PHP 页面调用,我几乎可以使用任何语言来执行复制。

有没有人遇到过这样的 PHP 脚本,或任何其他此类语言的脚本?有没有我可以发送 SQL 服务器为我执行此操作的命令?我确信我可以通过手动遍历结构并编写 SQL 语句来创建每个对象来找到自己的方法,但我希望有更简单的方法。

【问题讨论】:

    标签: php sql sql-server database clone


    【解决方案1】:

    您可以使用 SMO 轻松完成此操作。 Here's 一个为其提供特定代码的站点。代码在 C# 中,但希望您可以将其集成或翻译成 PHP。

    【讨论】:

    • 汤姆,非常感谢这篇文章。虽然没有透明的方法将该代码转换为 PHP(它使用某种我没有看到代码的 Visual Studio DLL),但它确实让我的谷歌搜索朝着正确的方向前进。这导致我找到上面的解决方案。为您的努力 +1!
    【解决方案2】:

    我找到了一种远程简单的方法来在 PHP 中完成此任务,并借助自定义编写的存储过程,该过程只需要存在于您希望克隆的数据库中(对我来说,它始终是 AccountDatabase_1)。您将表名称传递给存储过程,它会返回您需要运行以创建它的脚本(我们将在第二个数据库上执行此操作)。对于视图,创建脚本实际上存储在Information_Schema.Views 表中,因此您只需从中提取视图名称和创建代码即可非常轻松地创建克隆。

    存储过程 GenerateScript()

    USE [SOURCE_DATABASE_NAME]
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER Procedure [dbo].[GenerateScript] 
    (            
        @tableName varchar(100)
    )            
    as            
    If exists (Select * from Information_Schema.COLUMNS where Table_Name= @tableName)            
    Begin            
        declare @sql varchar(8000)            
        declare @table varchar(100)            
        declare @cols table (datatype varchar(50))          
        insert into @cols values('bit')          
        insert into @cols values('binary')          
        insert into @cols values('bigint')          
        insert into @cols values('int')          
        insert into @cols values('float')          
        insert into @cols values('datetime')          
        insert into @cols values('text')          
        insert into @cols values('image')          
        insert into @cols values('uniqueidentifier')          
        insert into @cols values('smalldatetime')          
        insert into @cols values('tinyint')          
        insert into @cols values('smallint')          
        insert into @cols values('sql_variant')          
    
        set @sql='' 
    
        Select 
            @sql=@sql+             
            case when charindex('(',@sql,1)<=0 then '(' else '' end +Column_Name + ' ' +Data_Type + 
            case when Column_name='id' then ' IDENTITY ' else '' end +            
            case when Data_Type in (Select datatype from @cols) then '' else  '(' end+
            case when data_type in ('real','money','decimal','numeric')  then cast(isnull(numeric_precision,'') as varchar)+','+
            case when data_type in ('real','money','decimal','numeric') then cast(isnull(Numeric_Scale,'') as varchar) end
            when data_type in ('char','nvarchar','nchar') then cast(isnull(Character_Maximum_Length,'') as varchar) else '' end+
            case when data_type ='varchar' and Character_Maximum_Length<0 then 'max' else '' end+
            case when data_type ='varchar' and Character_Maximum_Length>=0 then cast(isnull(Character_Maximum_Length,'') as varchar) else '' end+
            case when Data_Type in (Select datatype from @cols)then '' else  ')' end+
            case when Is_Nullable='No ' then ' Not null ' else ' null ' end + 
            case when Column_Default is not null then 'DEFAULT ' + Column_Default else '' end + ','
        from 
            Information_Schema.COLUMNS where Table_Name=@tableName            
    
        select  
            @table=  'Create table ' + table_Name 
        from 
            Information_Schema.COLUMNS 
        where 
            table_Name=@tableName            
    
        select @sql=@table + substring(@sql,1,len(@sql)-1) +' )'            
    
        select @sql  as DDL         
    
    End            
    
    Else        
        Select 'The table '+@tableName + ' does not exist'           
    

    PHP

    function cloneAccountDatabase($new_id){
    
        $srcDatabaseName = "AccountDatabase_1"; //The Database we are cloning
        $sourceConn = openDB($srcDatabaseName);
    
        $destDatabaseName = "AccountDatabase_".(int)$new_id;
        $destConn = openDB($destDatabaseName);
    
        //ENSURE DATABASE EXISTS, OR CREATE IT      
        if ($destConn==null){
            odbc_exec($sourceConn, "CREATE database " . $destDatabaseName);
            $destConn = openDB($destDatabaseName);
        }
    
        //BUILD ARRAY OF TABLE NAMES
        $tables = array();
        $q = odbc_exec($sourceConn, "SELECT name FROM sys.Tables");
        while (odbc_fetch_row($q))
            $tables[]=odbc_result($q,"name");
    
    
        //CREATE TABLES
        foreach ($tables as $tableName){
            $q=odbc_exec($sourceConn, "exec GenerateScript '$tableName';");
            odbc_fetch_row($q);
            $sql = odbc_result($q, 'ddl');
            $q=odbc_exec($destConn, $sql);
        }
    
        //BUILD ARRAY OF VIEW NAMES AND CREATE
        $q = odbc_exec($sourceConn, "SELECT * FROM Information_Schema.Views");
        while (odbc_fetch_row($q)){
            $view=odbc_result($q,"table_name");
            $sql = odbc_result($q, "view_definition");
            odbc_exec($destConn, $sql);
        }           
    
        return(true);   
    }
    

    更新

    CLONEDATABASE 函数在较新版本的 MSSQL 中可用。

    https://docs.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-clonedatabase-transact-sql?view=sql-server-2017

    //Clone AccountDatabase_1 to a database called AccountDatabase_2
    
    DBCC CLONEDATABASE (AccountDatabase_1, AccountDatabase_2) WITH VERIFY_CLONEDB, NO_STATISTICS;
    ALTER DATABASE AccountDatabase_2 SET READ_WRITE WITH NO_WAIT;
    

    【讨论】:

    • 显示错误:" Msg 208, Level 16, State 6, Procedure GenerateScript, Line 1 [Batch Start Line 6] Invalid object name 'dbo.GenerateScript'"
    • 首先,您需要执行第一个代码块来创建 dbo.GenerateScript -- 然后运行 ​​PHP 的第二个块。其次。这是一个旧的解决方案。看看CLONEDATABASEdocs.microsoft.com/en-us/sql/t-sql/database-console-commands/…
    猜你喜欢
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    • 2011-01-06
    相关资源
    最近更新 更多