AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 916
Accepted
bernd_k
bernd_k
Asked: 2011-01-27 08:28:07 +0800 CST2011-01-27 08:28:07 +0800 CST 2011-01-27 08:28:07 +0800 CST

Como copio uma tabela com SELECT INTO mas ignoro a propriedade IDENTITY?

  • 772

Eu tenho uma tabela com coluna de identidade diga:

create table with_id (
 id int identity(1,1),
 val varchar(30)
);

É bem conhecido, que este

select * into copy_from_with_id_1 from with_id;

resulta em copy_from_with_id_1 com identidade no id também.

A seguinte pergunta de estouro de pilha menciona a listagem de todas as colunas explicitamente.

Vamos tentar

select id, val into copy_from_with_id_2 from with_id;

Ops, mesmo neste caso id é uma coluna de identidade.

O que eu quero é uma mesa como

create table without_id (
 id int,
 val varchar(30)
);
sql-server sql-server-2005
  • 11 11 respostas
  • 68425 Views

11 respostas

  • Voted
  1. Best Answer
    Eric Humphrey - lotsahelp
    2011-01-27T10:46:50+08:002011-01-27T10:46:50+08:00

    De livros on-line

    O formato de new_table é determinado avaliando as expressões na lista de seleção. As colunas em new_table são criadas na ordem especificada pela lista de seleção. Cada coluna em new_table tem o mesmo nome, tipo de dados, nulidade e valor da expressão correspondente na lista de seleção. A propriedade IDENTITY de uma coluna é transferida, exceto sob as condições definidas em "Trabalhando com colunas de identidade" na seção Comentários.

    Abaixo da página:

    Quando uma coluna de identidade existente é selecionada em uma nova tabela, a nova coluna herda a propriedade IDENTITY, a menos que uma das seguintes condições seja verdadeira:

    • A instrução SELECT contém uma junção, cláusula GROUP BY ou função agregada.
    • Várias instruções SELECT são unidas usando UNION.
    • A coluna de identidade é listada mais de uma vez na lista de seleção.
    • A coluna de identidade faz parte de uma expressão.
    • A coluna de identidade é de uma fonte de dados remota.

    Se qualquer uma dessas condições for verdadeira, a coluna será criada NOT NULL em vez de herdar a propriedade IDENTITY. Se uma coluna de identidade for necessária na nova tabela, mas tal coluna não estiver disponível, ou você desejar um valor de semente ou incremento diferente da coluna de identidade de origem, defina a coluna na lista de seleção usando a função IDENTIDADE. Consulte "Criando uma coluna de identidade usando a função IDENTIDADE" na seção Exemplos abaixo.

    Então... teoricamente você poderia se safar com:

    select id, val 
    into copy_from_with_id_2 
    from with_id
    
    union all
    
    select 0, 'test_row' 
    where 1 = 0;
    

    Seria importante comentar este código para explicá-lo, para que ele não seja removido na próxima vez que alguém olhar para ele.

    • 61
  2. bernd_k
    2011-01-27T22:41:03+08:002011-01-27T22:41:03+08:00

    Inspirado na resposta de Erics, encontrei a seguinte solução que depende apenas dos nomes das tabelas e não usa nenhum nome de coluna específico:

    select * into without_id from with_id where 1 = 0
    union all
    select * from with_id where 1 = 0
    ;
    insert into without_id select * from with_id;
    

    Editar

    É até possível melhorar isso para

    select * into without_id from with_id
    union all
    select * from with_id where 1 = 0
    ;
    
    • 37
  3. Andriy M
    2016-05-13T05:08:42+08:002016-05-13T05:08:42+08:00

    Você pode usar uma junção para criar e preencher a nova tabela de uma só vez:

    SELECT
      t.*
    INTO
      dbo.NewTable
    FROM
      dbo.TableWithIdentity AS t
      LEFT JOIN dbo.TableWithIdentity ON 1 = 0
    ;
    

    Devido à 1 = 0condição, o lado direito não terá correspondências e, portanto, evitará a duplicação das linhas do lado esquerdo e, como essa é uma junção externa, as linhas do lado esquerdo também não serão eliminadas. Por fim, por se tratar de uma junção, a propriedade IDENTITY é eliminada.

    Selecionar apenas as colunas do lado esquerdo, portanto, produzirá uma cópia exata de dbo.TableWithIdentity somente em termos de dados, ou seja, com a propriedade IDENTITY removida.

    Tudo isso dito, Max Vernon levantou um ponto válido em um comentário que vale a pena ter em mente. Se você observar o plano de execução da consulta acima:

    Plano de execução

    você notará que a tabela de origem é mencionada no plano de execução apenas uma vez. A outra instância foi eliminada pelo otimizador.

    Portanto, se o otimizador puder estabelecer corretamente que o lado direito da junção não é necessário no plano, deve ser razoável esperar que em uma versão futura do SQL Server ele possa descobrir que a propriedade IDENTITY não precisa ser removido também, pois não há mais outra coluna IDENTITY na linha de origem definida de acordo com o plano de consulta. Isso significa que a consulta acima pode parar de funcionar conforme o esperado em algum momento.

    Mas, como corretamente observado por ypercubeᵀᴹ , até agora o manual tem declarado explicitamente que, se houver uma junção, a propriedade IDENTITY não será preservada:

    Quando uma coluna de identidade existente é selecionada em uma nova tabela, a nova coluna herda a propriedade IDENTITY, a menos que [...] [a] instrução SELECT contenha uma junção.

    Portanto, enquanto o manual continuar mencionando isso, provavelmente podemos ter certeza de que o comportamento permanecerá o mesmo.

    Parabéns a Shaneis e ypercubeᵀᴹ por trazer um tópico relacionado no chat.

    • 15
  4. Saurav Ghosh
    2014-01-28T04:02:39+08:002014-01-28T04:02:39+08:00

    Tente este código..

    SELECT isnull(Tablename_old.IDENTITYCOL + 0, -1) AS 'New Identity Column'
    INTO   dbo.TableName_new
    FROM   dbo.TableName_old 
    

    A ISNULLchamada garante que a nova coluna seja criada com NOT NULLnulidade.

    • 8
  5. bernd_k
    2011-02-14T06:22:42+08:002011-02-14T06:22:42+08:00

    Só para mostrar de uma forma diferente:

    Você pode usar um servidor vinculado .

    SELECT * 
    INTO without_id 
    FROM [linked_server].[source_db].dbo.[with_id];
    

    Você pode criar temporariamente um servidor vinculado ao servidor local usando isto:

    DECLARE @LocalServer SYSNAME 
    SET @LocalServer = @@SERVERNAME;
    EXEC master.dbo.sp_addlinkedserver @server = N'localserver'
        , @srvproduct = ''
        , @provider = 'SQLNCLI'
        , @datasrc = @LocalServer;
    EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'localserver'
        , @useself = N'True'
        , @locallogin = NULL
        , @rmtuser = NULL
        , @rmtpassword = NULL;
    

    Nesse ponto, você executaria o select * intocódigo, referenciando o localservernome de quatro partes do servidor vinculado:

    SELECT * 
    INTO without_id 
    FROM [localserver].[source_db].dbo.[with_id];
    

    Depois que isso for concluído, limpe o localserverservidor vinculado com isto:

    EXEC sp_dropserver @server = 'localserver'
        , @droplogins = 'droplogins';
    

    Ou você pode usar a OPENQUERYsintaxe

    SELECT * 
    INTO without_id 
    FROM OPENQUERY([linked_server], 'SELECT * FROM [source_db].dbo.[with_id]');
    
    • 3
  6. anon-99
    2016-03-02T01:49:03+08:002016-03-02T01:49:03+08:00

    A propriedade identity não é transferida se a instrução select contiver uma junção e, portanto,

    select a.* into without_id from with_id a inner join with_id b on 1 = 0;
    

    também dará o comportamento desejado (da idcoluna copiada para não manter a IDENTITYpropriedade. No entanto, terá o efeito colateral de não copiar nenhuma linha! (como em alguns outros métodos), então você precisará fazer:

    insert into without_id select * from with_id;
    

    (obrigado AakashM!)

    • 2
  7. FistOfFury
    2016-10-25T14:11:22+08:002016-10-25T14:11:22+08:00

    A maneira mais fácil é tornar a coluna parte de uma expressão.

    Exemplo:
    Se a tabela dbo.Employee tiver uma identidade na coluna ID, no exemplo abaixo, a tabela temporária #t também terá uma IDENTIDADE na coluna ID.

    --temp table has IDENTITY
    select ID, Name 
    into #t
    from dbo.Employee
    

    Altere isso para aplicar uma expressão ao ID e você #t não terá mais uma coluna IDENTITY on ID. Nesse caso, aplicamos uma adição simples à coluna ID.

    --no IDENTITY
    select ID = ID + 0, Name 
    into #t
    from dbo.Employee
    

    Outros exemplos de expressões para outros tipos de dados podem incluir: convert (), concatenação de strings ou Isnull ()

    • 1
  8. Tony
    2018-03-01T12:18:14+08:002018-03-01T12:18:14+08:00

    Às vezes, você deseja inserir de uma tabela onde você não sabe (ou se importa) se a coluna foi criada usando IDENTITY ou não. Pode até não ser uma coluna inteira com a qual você está trabalhando. Nesse caso, funcionará o seguinte:

    SELECT TOP(0) ISNULL([col],NULL) AS [col], ... INTO [table2] FROM [table1]
    ALTER TABLE [table2] REBUILD WITH (DATA_COMPRESSION=page)
    INSERT INTO [table2] ...
    

    ISNULL removerá o atributo IDENTITY da coluna, mas o inserirá com o mesmo nome e tipo da coluna original e também o tornará não anulável. TOP(0) criará uma tabela vazia que você pode usar para inserir linhas selecionadas. Você também pode compactar a tabela antes de inserir dados, se necessário.

    • 1
  9. john hunter
    2017-10-16T07:20:00+08:002017-10-16T07:20:00+08:00
    select convert(int, id) as id, val 
    into copy_from_with_id_without_id 
    from with_id;
    

    removerá a identidade.

    A desvantagem é que idse torna anulável, mas você pode adicionar essa restrição.

    • 0
  10. Viraj Sandaruwan
    2020-09-23T09:06:16+08:002020-09-23T09:06:16+08:00

    Tente a seguinte consulta: Encontrei esta funcionando corretamente. Isso selecionará dados em colunas sem identidade = 1

    DECLARE @Temp NVARCHAR(MAX); 
    DECLARE @SQL NVARCHAR(MAX);
    
    SET @Temp = '';
    SELECT @Temp = @Temp + COLUMN_NAME + ', ' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='Person' AND  columnProperty(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') != 1 
    
    SET @SQL = 'SELECT ' + SUBSTRING(@Temp, 0, LEN(@Temp)) +' FROM [Person]';
    EXECUTE SP_EXECUTESQL @SQL;
    

    Você pode obter os detalhes do nome da coluna na tabela sys.columns

    Tente a seguinte consulta:

    SELECT * FROM SYS.COLUMNS 
    WHERE object_id = OBJECT_ID('dbo.TableName') 
    AND [Name] <> 'ColumnName'
    
    DECLARE @sql as VARCHAR(8000)
    SET @sql = 'SELECT '
    
    SELECT @sql += [Name] + ', ' FROM SYS.COLUMNS 
    WHERE object_id = OBJECT_ID('dbo.TableName') 
    AND [Name] <> 'ColumnName'
    
    SELECT @sql += ' FROM Dbo.TableName'
    
    EXEC(@sql)
    
    • -1

relate perguntas

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

  • Downgrade do SQL Server 2008 para 2005

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como você mostra o SQL em execução em um banco de dados Oracle?

    • 2 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Posso ver Consultas Históricas executadas em um banco de dados SQL Server?

    • 6 respostas
  • Marko Smith

    Como uso currval() no PostgreSQL para obter o último id inserido?

    • 10 respostas
  • Marko Smith

    Como executar o psql no Mac OS X?

    • 11 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Marko Smith

    Passando parâmetros de array para um procedimento armazenado

    • 12 respostas
  • Martin Hope
    Manuel Leduc Restrição exclusiva de várias colunas do PostgreSQL e valores NULL 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler Quando uma chave primária deve ser declarada sem cluster? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - Qual é melhor como chave primária? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick Como posso otimizar um mysqldump de um banco de dados grande? 2011-01-04 13:13:48 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve