将 SQL Server 2008 数据库架构克隆到新数据库 - 以编程方式(PHP?)

发布于 2024-12-01 08:57:01 字数 789 浏览 1 评论 0原文

我已经做了一些谷歌搜索和搜索,但我在此事上找不到太多帮助。我正在设计一个利用 Microsoft SQL Server 2008 服务器的 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 语句来创建每个对象的方法,但我希望有更简单的方法。

I've done some Googling and searching on SO, but I have not been able to find much help on the matter. I am designing a web service which utilizes an Microsoft SQL Server 2008 Server. The relevant structure is something like this... There is a main database which houses all Primary Account/Company information (Company name, address, etc..). In addition, there are databases for each Account/Company which houses all of the relevant (meta?)data for that account (users, settings, etc...).

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

When a new account is created (let's say, ID=3), I am trying to figure out a way to clone the table schema and views (NOT the data) of AccountDatabase0001 into a new database called AccountDatabase00003. I could use virtually any language to perform the duplication as long as it can be called from a PHP page somehow.

Has anyone come across such a PHP script, or a script in any other such language for that matter? Is there a command I can send the the SQL server to do this for me? I'm sure I could find my way through manually traversing the structure and writing SQL statements to create each object, but I'm hoping for something more simple.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

执妄 2024-12-08 08:57:01

You can do this using SMO without too much trouble. Here's one site that gives specific code for it. The code is in C#, but hopefully you can integrate it or translate it into PHP.

忆悲凉 2024-12-08 08:57:01

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

STORED PROCGenerateScript()

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);   
}

UPDATE

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

https://learn.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;

I found a remotely simply way to accomplish this in PHP with a little help from a custom-written stored procedure which need only exist in the database you wish to clone (for me it's always AccountDatabase_1). You pass the Table name to the Stored Procedure, and it returns the script you need to run in order to create it (which we will do, on the second database). For views, the creation script is actually stored in the Information_Schema.Views table, so you can just pull the view names and creation code from that to create clones very easily.

STORED PROC 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);   
}

UPDATE

The CLONEDATABASE function is available in newer versions of MSSQL.

https://learn.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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文