Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come copiare uno schema di tabella e vincoli su una tabella di database diversi?

Sicuramente sono passati 2 anni, ma volevo contribuire con una soluzione. Questa procedura copia una tabella in "BackUp__ e il relativo vincolo di chiave primaria. Racchiude il nome della tabella con il carattere jolly '%' per consentire la copia di un gruppo di tabelle. Sto solo spostando il chiave primaria perché non si fa affidamento su altre tabelle, quindi meno mal di testa. Inoltre, nessun cursore!

ALTER PROCEDURE dbo.Admin_CopyTable
     @TableName NVARCHAR(255)
AS
BEGIN

    -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
    SET NOCOUNT ON;

    -- is there any work to do?
    IF NOT (isNull(@TableName,'')='')
    BEGIN
        -- Get list of all tables that match the @TableName wildcard
        DECLARE @tables TABLE (id BIGINT IDENTITY(1,1), [name] NVARCHAR(255)) -- using id as means to avoid cursor
        INSERT INTO @tables SELECT table_name FROM information_schema.tables WHERE table_name LIKE '%' + @TableName + '%' AND table_name NOT LIKE 'BackUp_%' ORDER BY table_name

        -- Go through each table and copy it
        DECLARE @row BIGINT;
        DECLARE @thisTable AS NVARCHAR(255);
        DECLARE @dSQL  NVARCHAR(4000);      -- holds the SQL string to execute and copy table data
        DECLARE @TablePrefix NVARCHAR(255); -- Name that is prepended before the name of the actual table to show it is a backup table

        -- set default prefix by adding todays date to the table name
        SELECT @TablePrefix = 'BackUp_' + CONVERT(NVARCHAR(10), GetDate(), 112) + '_'; -- Date as YYYYMMDD

        -- Get first row for looping through list of tables
        SELECT @row = MIN(id) FROM @tables;

        WHILE (isNull(@row, 0) <> 0)    -- returns null when no more rows, which gets converted to 0 (zero)
        BEGIN
            SELECT @thisTable = [name] FROM @tables where id = @row

            IF NOT EXISTS(SELECT table_name FROM information_schema.tables WHERE table_name like @TablePrefix + @thisTable)
              BEGIN
                SET @dSQL = 'Select * Into ' + @TablePrefix + @thisTable + ' from ' + @thisTable;
                EXEC (@dSQL)
                PRINT @TablePrefix + @thisTable + ': Data Backed up.'

                -- Copy the Primary Key into the Backup table
                BEGIN   
                    -- Get list of all the columns that make up the Primary Key
                    -- for composite PK's = one row per pk column
                    DECLARE @PKColsTbl table ([name] NVARCHAR(255), col NVARCHAR(255))

                    INSERT INTO @PKColsTbl
                    SELECT  c.Constraint_Name, c.COLUMN_NAME  
                    FROM    INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk 
                           ,INFORMATION_SCHEMA.KEY_COLUMN_USAGE c 
                    WHERE   pk.TABLE_NAME = @thisTable 
                        and CONSTRAINT_TYPE = 'PRIMARY KEY' 
                        and c.TABLE_NAME = pk.TABLE_NAME 
                        and c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME 

                    -- Transpose rows into one column as a comma delimeted string
                    DECLARE @pkCol NVARCHAR(255);
                    SELECT @pkCol = stuff((select ',' + col from @PKColsTbl for XML PATH('')), 1,1,'')

                    -- Build the dynamic SQL statement and execute it
                    SET @dSQL = 'ALTER TABLE ' + @TablePrefix + @thisTable + ' ADD CONSTRAINT ' + 'PK_' + @TablePrefix + @thisTable + ' PRIMARY KEY (' + @pkCol + ')'
                    EXEC (@dSQL)
                    PRINT @TablePrefix + @thisTable + ': PK Created.'

                    -- Since its a loop, clear out the table
                    DELETE FROM @PKColsTbl
                END
                -- END of Copying the Primary Key

              END
            ELSE 
              BEGIN
                PRINT @TablePrefix + @thisTable + ': Exists!'
              END

            -- Get next row
            SELECT @row = min(id) FROM @tables WHERE id > @row
        END
    END
END