Créer une table (structure) à partir d'une table existante

100

Comment créer une nouvelle table dont la structure doit être identique à une autre table

j'ai essayé

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

mais son erreur ne fonctionnait pas

Domnique
la source
très utile, intrigant d'avoir une clause where qui est toujours fausse!
JosephDoggie

Réponses:

167

Essayer:

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

Notez que cela ne copiera pas les index, les clés, etc.

Si vous souhaitez copier l' intégralité structure , vous devez générer un script de création de la table. Vous pouvez utiliser ce script pour créer une nouvelle table avec la même structure. Vous pouvez ensuite également vider les données dans la nouvelle table si vous en avez besoin.

Si vous utilisez Enterprise Manager, cliquez simplement avec le bouton droit sur la table et sélectionnez Copier pour générer un script de création.

Kevin Crowell
la source
1
Kevin, juste un petit changement de mise en forme dans votre réponse: - Sélectionnez * Dans <DestinationTableName> De <SourceTableName> Où 1 = 2
Ashish Gupta
6
Qutbuddin, 1 = 2 empêchera la copie des données de la table source vers la table de destination. Essayez vous-même: - CREATE TABLE Table1 (Id int, Nom varchar (200)) INSERT INTO table1 VALUES (1, 'A') INSERT INTO table1 VALUES (2, 'B') - Créera table2 avec les données de la table1 SELECT * INTO Table2 FROM Table1 WHERE 1 = 2 - Crée une table2 sans données dans la table1 SELECT * INTO Table2 FROM Table1 WHERE 1 = 2
Ashish Gupta
Je pensais que 1 = 2 serait juste un mauvais argument bizarre afin d'éviter de copier des données.
Arthur Zennig
44

C'est ce que j'utilise pour cloner une structure de table (colonnes uniquement) ...

SELECT TOP 0 *
INTO NewTable
FROM TableStructureIWishToClone
DanielM
la source
1
Cette solution est plus claire que d'avoir la condition supplémentaire "1 = 2", je recommanderais ceci
Pinte Dani
30

Copier la structure uniquement (copier toutes les colonnes)

Select Top 0 * into NewTable from OldTable

Copier la structure uniquement (copier certaines colonnes)

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

Copier la structure avec les données

Select * into NewTable from OldTable

Si vous avez déjà une table avec la même structure et que vous souhaitez simplement copier des données, utilisez ceci

Insert into NewTable Select * from OldTable
Abhishek Maurya
la source
A travaillé pour moi dans MSSQL 2008 R2
Pyrite
Excellente solution, simple et élégante. Y a-t-il un hack pour créer cette copie d'index et de clés primaires également?
Tumaini Mosha
16
Create table abc select * from def limit 0;

Ce sera un travail définitif

GIRDHAR SINGH
la source
Parfait! Merci
Dylan B
14

POUR MYSQL:

Vous pouvez utiliser:

CREATE TABLE foo LIKE bar;

Documentation ici .

Francesco Gusmeroli
la source
21
La question est étiquetée comme sql-serverpour laquelle cette syntaxe n'est pas valide, fyi.
Molomby
Ne devrait pas compter comme réponse en raison de la relation avec MySQL et non avec le serveur SQL
celerno
2
FYI - cela conserve également les clés primaires et les index, conservés.
garg10mai
8

Il est probablement également intéressant de mentionner que vous pouvez effectuer les opérations suivantes:

Cliquez avec le bouton droit sur la table que vous souhaitez dupliquer > Script Table As > Create To > Fenêtre Nouvel éditeur de requête

Ensuite, où est dit le nom de la table sur laquelle vous venez de cliquer avec le bouton droit dans le script qui a été généré, changez le nom en ce que vous voulez que votre nouvelle table soit appelée et cliquez sur Execute

JsonStatham
la source
5

essayez ceci .. celui ci-dessous copie la structure entière de la table existante mais pas les données.

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

si vous souhaitez copier les données, utilisez celle ci-dessous:

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

J'utilise le processus stocké suivant pour copier le schéma d'une table, y compris PK, index, état de la partition. Ce n'est pas très rapide, mais semble faire le travail. Je suis heureux de recevoir des idées pour l'accélérer:

    /*
        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
la source
1
Rendre cela plus rapide peut être aussi simple que de déclarer vos curseurs CURSOR LOCAL FAST_FORWARD. Personnellement, j'essaie de créer un script similaire sans utiliser de curseurs et de voir comment cela fonctionne.
mendosi
Salut @mendosi Je sais que c'est vieux, mais je cherche actuellement à générer un script CREATE avec toutes les choses diverses (contraintes / index / partitions / déclencheurs / etc) ainsi que la définition de colonne. Je me demandais si vous aviez réussi à recréer cela avec une approche sans curseur. si oui, cela vous dérangerait-il de le partager? Très apprécié, merci
007
Le script que j'ai écrit copie une ou plusieurs tables et n'utilise pas de curseur. C'est aussi trop gros pour un commentaire. Au lieu de cela, je vais créer un
mendosi
4
  1. Si vous souhaitez copier la même base de données

    Select * INTO NewTableName from OldTableName
  2. Si une autre base de données

    Select * INTO NewTableName from DatabaseName.OldTableName
cd pandey
la source
3
SELECT * 
INTO NewTable
FROM OldTable
WHERE 1 = 2
Chris Latta
la source
3

Je ne sais pas pourquoi vous voulez faire ça, mais essayez:

SELECT *
INTO NewTable
FROM OldTable
WHERE 1 = 2

Cela devrait marcher.

Adrian Fâciu
la source
Je pense que cela copierait également les données? il ne veut que la structure.
Ashish Gupta
@Ashis Gupta - Merci, j'ai oublié le "où" :)
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
la source
2
cela ne copie pas les contraintes et les clés
Trikaldarshi
2

J'ai trouvé ici ce que je cherchais. Cela m'a aidé à me rappeler ce que j'utilisais il y a 3-4 ans.

Je voulais réutiliser la même syntaxe pour pouvoir créer une table avec des données résultant de la jointure d'une table.

Est venu avec la requête ci-dessous après quelques tentatives.

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
la source
0
SELECT * INTO newtable
from Oldtable
BalaRam
la source
Veuillez utiliser le balisage de code pour une meilleure lisibilité, ce qui est également plus utile pour expliquer un peu votre code.
Nima Derakhshanjan
Merci pour cet extrait de code, qui peut fournir une aide immédiate. Une explication appropriée améliorerait considérablement sa valeur éducative en montrant pourquoi c'est une bonne solution au problème, et la rendrait plus utile aux futurs lecteurs avec des questions similaires, mais pas identiques. En particulier, il regarde l'œil non averti comme si cela copierait également le contenu de Oldtable. Comment cela est-il évité?
Toby Speight