Erstellen Sie eine Tabelle (Struktur) aus einer vorhandenen Tabelle

99

So erstellen Sie eine neue Tabelle, deren Struktur mit einer anderen Tabelle identisch sein sollte

Ich habe es versucht

CREATE TABLE dom AS SELECT * FROM dom1 WHERE 1=2

Es ist jedoch kein Fehler aufgetreten

Domnic
quelle
Sehr hilfreich, faszinierend, eine where-Klausel zu haben, die immer falsch ist!
JosephDoggie

Antworten:

166

Versuchen:

Select * Into <DestinationTableName> From <SourceTableName> Where 1 = 2

Beachten Sie, dass dadurch keine Indizes, Schlüssel usw. kopiert werden.

Wenn Sie die gesamte Struktur kopieren möchten , müssen Sie ein Erstellungsskript der Tabelle generieren. Mit diesem Skript können Sie eine neue Tabelle mit derselben Struktur erstellen. Sie können die Daten dann bei Bedarf auch in die neue Tabelle kopieren.

Wenn Sie Enterprise Manager verwenden, klicken Sie einfach mit der rechten Maustaste auf die Tabelle und wählen Sie Kopieren, um ein Skript zum Erstellen zu erstellen.

Kevin Crowell
quelle
1
Kevin, nur eine kleine Formatierungsänderung in Ihrer Antwort: - Wählen Sie * Into <DestinationTableName> aus <SourceTableName> Wobei 1 = 2
Ashish Gupta
6
Qutbuddin, 1 = 2 verhindert das Kopieren von Daten von der Quell- in die Zieltabelle. Versuchen Sie es selbst: - TABELLE ERSTELLEN Tabelle1 (ID int, Name varchar (200)) INSERT IN table1 VALUES (1, 'A') INSERT IN table1 VALUES (2, 'B') - Erstellt Tabelle2 mit Daten in Tabelle1 SELECT * INTO Tabelle2 FROM Table1 WHERE 1 = 2 - Erstellt Tabelle2 ohne Daten in Tabelle1 SELECT * INTO Table2 FROM Table1 WHERE 1 = 2
Ashish Gupta
Ich dachte, 1 = 2 wäre nur ein seltsames falsches Argument, um das Kopieren von Daten zu vermeiden.
Arthur Zennig
44

Dies ist, was ich verwende, um eine Tabellenstruktur zu klonen (nur Spalten) ...

SELECT TOP 0 *
INTO NewTable
FROM TableStructureIWishToClone
DanielM
quelle
1
Diese Lösung ist klarer als die zusätzliche Bedingung "1 = 2", ich würde dies empfehlen
Pinte Dani
30

Nur Struktur kopieren (alle Spalten kopieren)

Select Top 0 * into NewTable from OldTable

Nur Struktur kopieren (einige Spalten kopieren)

Select Top 0 Col1,Col2,Col3,Col4,Col5 into NewTable from OldTable

Struktur mit Daten kopieren

Select * into NewTable from OldTable

Wenn Sie bereits eine Tabelle mit derselben Struktur haben und nur Daten kopieren möchten, verwenden Sie diese

Insert into NewTable Select * from OldTable
Abhishek Maurya
quelle
Arbeitete für mich in MSSQL 2008 R2
Pyrite
Tolle Lösung, einfach und elegant. Gibt es einen Hack, um diese Kopie auch Indizes und Primärschlüssel zu erstellen?
Tumaini Mosha
16
Create table abc select * from def limit 0;

Dies wird definitiv funktionieren

GIRDHAR SINGH
quelle
Perfekt! Vielen Dank
Dylan B
14

FÜR MYSQL:

Sie können verwenden:

CREATE TABLE foo LIKE bar;

Dokumentation hier .

Francesco Gusmeroli
quelle
20
Die Frage ist mit dem Tag versehen, sql-serverfür das diese Syntax nicht gültig ist.
Molomby
Sollte aufgrund der Beziehung zu MySQL und nicht zu SQL-Server nicht als Antwort gelten
Celerno
2
Zu Ihrer Information - hier bleiben auch Primärschlüssel und Indizes erhalten.
Garg10Mai
8

Es ist wahrscheinlich auch erwähnenswert, dass Sie Folgendes tun können:

Klicken Sie mit der rechten Maustaste auf die Tabelle, die Sie duplizieren möchten. > Skripttabelle als > Erstellen an > Neues Abfrageeditorfenster

Wenn dort der Name der Tabelle steht, auf die Sie in dem generierten Skript mit der rechten Maustaste geklickt haben, ändern Sie den Namen in den Namen, in den Ihre neue Tabelle aufgerufen werden soll, und klicken Sie auf Execute

JsonStatham
quelle
5

Versuchen Sie dies. Die folgende Kopie kopiert die gesamte Struktur der vorhandenen Tabelle, jedoch nicht die Daten.

create table AT_QUOTE_CART as select * from QUOTE_CART where 0=1 ;

Wenn Sie die Daten kopieren möchten, verwenden Sie die folgende:

create table AT_QUOTE_CART as select * from QUOTE_CART ;
Abhi Urs
quelle
5

Ich verwende den folgenden gespeicherten Prozess zum Kopieren des Schemas einer Tabelle, einschließlich PK, Indizes und Partitionsstatus. Es ist nicht sehr schnell, scheint aber den Job zu machen. Ich begrüße alle Ideen, wie man es beschleunigen kann:

    /*
        Clones a table's schema from an existing table (without data)
        if target table exists, it will be dropped first.
        The following schema elements are cloned:
            * Structure
            * Primary key
            * Indexes
            * Constraints
    DOES NOT copy:
        * Triggers
        * File groups

    ASSUMPTION: constraints are uniquely named with the table name, so that we dont end up with duplicate constraint names
*/
CREATE PROCEDURE [dbo].[spCloneTableStructure]

@SourceTable            nvarchar(255),
@DestinationTable       nvarchar(255),
@PartionField           nvarchar(255),
@SourceSchema           nvarchar(255) = 'dbo',  
@DestinationSchema      nvarchar(255) = 'dbo',    
@RecreateIfExists       bit = 1

AS
BEGIN

DECLARE @msg  nvarchar(200), @PartionScript nvarchar(255), @sql NVARCHAR(MAX)

    IF EXISTS(Select s.name As SchemaName, t.name As TableName
                        From sys.tables t
                        Inner Join sys.schemas s On t.schema_id = s.schema_id
                        Inner Join sys.partitions p on p.object_id = t.object_id
                        Where p.index_id In (0, 1) and t.name = @SourceTable
                        Group By s.name, t.name
                        Having Count(*) > 1)

        SET @PartionScript = ' ON [PS_PartitionByCompanyId]([' + @PartionField + '])'
    else
        SET @PartionScript = ''

SET NOCOUNT ON;
BEGIN TRY   
    SET @msg ='  CloneTable  ' + @DestinationTable + ' - Step 1, Drop table if exists. Timestamp: '  + CONVERT(NVARCHAR(50),GETDATE(),108)
     RAISERROR( @msg,0,1) WITH NOWAIT
    --drop the table
    if EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @DestinationTable)
    BEGIN
        if @RecreateIfExists = 1
            BEGIN
                exec('DROP TABLE [' + @DestinationSchema + '].[' + @DestinationTable + ']')
            END
        ELSE
            RETURN
    END

    SET @msg ='  CloneTable  ' + @DestinationTable + ' - Step 2, Create table. Timestamp: '  + CONVERT(NVARCHAR(50),GETDATE(),108)
    RAISERROR( @msg,0,1) WITH NOWAIT
    --create the table
    exec('SELECT TOP (0) * INTO [' + @DestinationTable + '] FROM [' + @SourceTable + ']')       

    --create primary key
    SET @msg ='  CloneTable  ' + @DestinationTable + ' - Step 3, Create primary key. Timestamp: '  + CONVERT(NVARCHAR(50),GETDATE(),108)
    RAISERROR( @msg,0,1) WITH NOWAIT
    DECLARE @PKSchema nvarchar(255), @PKName nvarchar(255),@count   INT
    SELECT TOP 1 @PKSchema = CONSTRAINT_SCHEMA, @PKName = CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = @SourceSchema AND TABLE_NAME = @SourceTable AND CONSTRAINT_TYPE = 'PRIMARY KEY'
    IF NOT @PKSchema IS NULL AND NOT @PKName IS NULL
    BEGIN
        DECLARE @PKColumns nvarchar(MAX)
        SET @PKColumns = ''

        SELECT @PKColumns = @PKColumns + '[' + COLUMN_NAME + '],'
            FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
            where TABLE_NAME = @SourceTable and TABLE_SCHEMA = @SourceSchema AND CONSTRAINT_SCHEMA = @PKSchema AND CONSTRAINT_NAME= @PKName
            ORDER BY ORDINAL_POSITION

        SET @PKColumns = LEFT(@PKColumns, LEN(@PKColumns) - 1)

        exec('ALTER TABLE [' + @DestinationSchema + '].[' + @DestinationTable + '] ADD  CONSTRAINT [PK_' + @DestinationTable + '] PRIMARY KEY CLUSTERED (' + @PKColumns + ')' + @PartionScript);
    END

    --create other indexes
    SET @msg ='  CloneTable  ' + @DestinationTable + ' - Step 4, Create Indexes. Timestamp: '  + CONVERT(NVARCHAR(50),GETDATE(),108)
    RAISERROR( @msg,0,1) WITH NOWAIT
    DECLARE @IndexId int, @IndexName nvarchar(255), @IsUnique bit, @IsUniqueConstraint bit, @FilterDefinition nvarchar(max), @type int

    set @count=0
    DECLARE indexcursor CURSOR FOR
    SELECT index_id, name, is_unique, is_unique_constraint, filter_definition, type FROM sys.indexes WHERE is_primary_key = 0 and object_id = object_id('[' + @SourceSchema + '].[' + @SourceTable + ']')
    OPEN indexcursor;
    FETCH NEXT FROM indexcursor INTO @IndexId, @IndexName, @IsUnique, @IsUniqueConstraint, @FilterDefinition, @type
    WHILE @@FETCH_STATUS = 0
       BEGIN
            set @count =@count +1
            DECLARE @Unique nvarchar(255)
            SET @Unique = CASE WHEN @IsUnique = 1 THEN ' UNIQUE ' ELSE '' END

            DECLARE @KeyColumns nvarchar(max), @IncludedColumns nvarchar(max)
            SET @KeyColumns = ''
            SET @IncludedColumns = ''

            select @KeyColumns = @KeyColumns + '[' + c.name + '] ' + CASE WHEN is_descending_key = 1 THEN 'DESC' ELSE 'ASC' END + ',' from sys.index_columns ic
            inner join sys.columns c ON c.object_id = ic.object_id and c.column_id = ic.column_id
            where index_id = @IndexId and ic.object_id = object_id('[' + @SourceSchema + '].[' + @SourceTable + ']') and key_ordinal > 0
            order by index_column_id

            select @IncludedColumns = @IncludedColumns + '[' + c.name + '],' from sys.index_columns ic
            inner join sys.columns c ON c.object_id = ic.object_id and c.column_id = ic.column_id
            where index_id = @IndexId and ic.object_id = object_id('[' + @SourceSchema + '].[' + @SourceTable + ']') and key_ordinal = 0
            order by index_column_id

            IF LEN(@KeyColumns) > 0
                SET @KeyColumns = LEFT(@KeyColumns, LEN(@KeyColumns) - 1)

            IF LEN(@IncludedColumns) > 0
            BEGIN
                SET @IncludedColumns = ' INCLUDE (' + LEFT(@IncludedColumns, LEN(@IncludedColumns) - 1) + ')'
            END

            IF @FilterDefinition IS NULL
                SET @FilterDefinition = ''
            ELSE
                SET @FilterDefinition = 'WHERE ' + @FilterDefinition + ' '

            SET @msg ='  CloneTable  ' + @DestinationTable + ' - Step 4.' + CONVERT(NVARCHAR(5),@count) + ', Create Index ' + @IndexName + '. Timestamp: '  + CONVERT(NVARCHAR(50),GETDATE(),108)
            RAISERROR( @msg,0,1) WITH NOWAIT

            if @type = 2
                SET @sql = 'CREATE ' + @Unique + ' NONCLUSTERED INDEX [' + @IndexName + '] ON [' + @DestinationSchema + '].[' + @DestinationTable + '] (' + @KeyColumns + ')' + @IncludedColumns + @FilterDefinition  + @PartionScript
            ELSE
                BEGIN
                    SET @sql = 'CREATE ' + @Unique + ' CLUSTERED INDEX [' + @IndexName + '] ON [' + @DestinationSchema + '].[' + @DestinationTable + '] (' + @KeyColumns + ')' + @IncludedColumns + @FilterDefinition + @PartionScript
                END
            EXEC (@sql)
            FETCH NEXT FROM indexcursor INTO @IndexId, @IndexName, @IsUnique, @IsUniqueConstraint, @FilterDefinition, @type
       END
    CLOSE indexcursor
    DEALLOCATE indexcursor

    --create constraints
    SET @msg ='  CloneTable  ' + @DestinationTable + ' - Step 5, Create constraints. Timestamp: '  + CONVERT(NVARCHAR(50),GETDATE(),108)
    RAISERROR( @msg,0,1) WITH NOWAIT
    DECLARE @ConstraintName nvarchar(max), @CheckClause nvarchar(max), @ColumnName NVARCHAR(255)
    DECLARE const_cursor CURSOR FOR
        SELECT
            REPLACE(dc.name, @SourceTable, @DestinationTable),[definition], c.name
        FROM sys.default_constraints dc
            INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id
        WHERE OBJECT_NAME(parent_object_id) =@SourceTable               
    OPEN const_cursor
    FETCH NEXT FROM const_cursor INTO @ConstraintName, @CheckClause, @ColumnName
    WHILE @@FETCH_STATUS = 0
       BEGIN
            exec('ALTER TABLE [' + @DestinationTable + '] ADD CONSTRAINT [' + @ConstraintName + '] DEFAULT ' + @CheckClause + ' FOR ' + @ColumnName)
            FETCH NEXT FROM const_cursor INTO @ConstraintName, @CheckClause, @ColumnName
       END;
    CLOSE const_cursor
    DEALLOCATE const_cursor                 


END TRY
    BEGIN CATCH
        IF (SELECT CURSOR_STATUS('global','indexcursor')) >= -1
        BEGIN
         DEALLOCATE indexcursor
        END

        IF (SELECT CURSOR_STATUS('global','const_cursor')) >= -1
        BEGIN
         DEALLOCATE const_cursor
        END


        PRINT 'Error Message: ' + ERROR_MESSAGE(); 
    END CATCH

END

GO
Steve Faiwiszewski
quelle
1
Dies schneller zu machen ist möglicherweise so einfach wie das Deklarieren Ihrer Cursor als CURSOR LOCAL FAST_FORWARD. Persönlich versuche ich, ein ähnliches Skript ohne Verwendung von Cursorn zu erstellen und zu sehen, wie dies funktioniert.
Mendosi
Hallo @mendosi, ich weiß, dass es alt ist, aber ich bin gerade dabei, ein CREATE-Skript mit all den verschiedenen Dingen (Einschränkungen / Indizes / Partitionen / Trigger / usw.) zusammen mit der Spaltendefinition zu generieren. Ich habe mich gefragt, ob es Ihnen gelungen ist, dies mit einem Nicht-Cursor-Ansatz neu zu erstellen. Wenn ja, würde es Ihnen etwas ausmachen, es zu teilen? Sehr geschätzt, danke
007
Das Skript, das ich geschrieben habe, kopiert eine oder mehrere Tabellen und verwendet keinen Cursor. Es ist auch zu groß für einen Kommentar. Stattdessen verlinke ich zu Hans Michiels Skript: hansmichiels.com/2016/02/18/…
mendosi
3
SELECT * 
INTO NewTable
FROM OldTable
WHERE 1 = 2
Chris Latta
quelle
3

Ich weiß nicht, warum Sie das tun wollen, aber versuchen Sie:

SELECT *
INTO NewTable
FROM OldTable
WHERE 1 = 2

Es sollte funktionieren.

Adrian Fâciu
quelle
Ich denke das würde auch die Daten kopieren? er will nur die Struktur.
Ashish Gupta
@ Ashis Gupta - Danke, ich habe das "Wo" vergessen :)
Adrian Fâciu
3
Copy the table structure:-
select * into newtable from oldtable where 1=2;

Copy the table structure along with table data:-
select * into newtable from oldtable where 1=1;
NameNotFoundException
quelle
2
Dies kopiert keine Einschränkungen und Schlüssel
Trikaldarshi
3
  1. Wenn Sie dieselbe Datenbank kopieren möchten

    Select * INTO NewTableName from OldTableName
  2. Wenn eine andere Datenbank

    Select * INTO NewTableName from DatabaseName.OldTableName
cd pandey
quelle
2

Fand hier was ich suchte. Hat mir geholfen, mich daran zu erinnern, was ich vor 3-4 Jahren benutzt habe.

Ich wollte dieselbe Syntax wiederverwenden, um eine Tabelle mit Daten erstellen zu können, die sich aus dem Join einer Tabelle ergeben.

Kam nach einigen Versuchen mit der folgenden Abfrage auf.

SELECT a.*
INTO   DetailsArchive
FROM   (SELECT d.*
        FROM   details AS d
               INNER JOIN
               port AS p
               ON p.importid = d.importid
        WHERE  p.status = 2) AS a;
user_v
quelle
0
SELECT * INTO newtable
from Oldtable
BalaRam
quelle
Verwenden Sie zur besseren Lesbarkeit das Code-Markup. Dies ist auch nützlicher, um ein wenig über Ihren Code zu erklären.
Nima Derakhshanjan
Vielen Dank für dieses Code-Snippet, das möglicherweise sofortige Hilfe bietet. Eine richtige Erklärung würde den Bildungswert erheblich verbessern , indem sie zeigt, warum dies eine gute Lösung für das Problem ist, und sie für zukünftige Leser mit ähnlichen, aber nicht identischen Fragen nützlicher machen. Insbesondere sieht es für das ungeübte Auge so aus, als würde dies auch den Inhalt von kopieren Oldtable. Wie wird das vermieden?
Toby Speight