none
INSERT com SELECT. As vezes executa com sucesso, as vezes da a mensagem "Column name or number of supplied values does not match table definition." SQL 2000/2008 RRS feed

  • Pergunta

  • Senhores, boa tarde...

    Tenho o seguinte cenário

    /* Tabelas criadas em SQL 2000 para o primeiro teste e em SQL 2008 para o segundo teste */ create table Resumo (id int , nome varchar(10), valor int, usuario varchar(10) , fake int ) Create table vendas (id int, nome varchar(10), valor int, usuario varchar(10)) insert into vendas (id, nome, valor, usuario ) values (1,'jose', 10, 'ze') /* Tanto no INSERT como no SELECT não foram declaradas as colunas Na tabele RESUMO temos 5 colunas. Na tabela VENDAS, temos 4 colunas. Fazendo o comando abaixo com ORDER BY, comando executado com sucess. */ insert into resumo select * from vendas order by 1 /* Fazendo o mesmo comando, sem order by */ insert into resumo select * from vendas

    Msg 213, Level 16, State 4, Line 1 Insert Error: Column name or number of supplied values does not match table definition.

    Repetindo o comando no SQL 2008, tanto como ORDER BY ou sem, a a mensagem de erro.

    Entendo que no SQL 2008 foi alterado o comportamento no Engine para esse caso. O que gostaria de achar um KB na Microsoft que fala desse comportamento para passar para a equipe de desenvolvimento.

    Por acaso alguem sabe se tem esse KB?

    Grato,


    Wolney

    terça-feira, 26 de março de 2013 18:46

Respostas

  • Somente para deixar registrado mais um comentário sobre o assunto. A resposta foi feito pelo João Bosel Polisel que faz parte do grupo MSSQL-L do Yahoo Groups.

    De: mssql-l@yahoogrupos.com.br [mailto:mssql-l@yahoogrupos.com.br] Em nome de João Polisel
    Enviada em: quarta-feira, 27 de março de 2013 16:18
    Para: mssql-l@yahoogrupos.com.br
    Assunto: RE: [mssql-l] INSERT com SELECT. As vezes executa com sucesso, as vezes da a mensagem "Column name or number of supplied values does not match table definition." SQL 2000

    Wolney,

    Não creio que haja um KB falando disso, mas é verdade que o SQL 2000 era “uma mãe” para consertar erros de desenvolvimento em runtime e isso foi removido a partir do 2005.

    A filosofia do produto teve que mudar, porque por mais que se fizesse não há como você prever, detectar e corrigir todos os erros e inconsistências no código, e isso tornava o comportamento do SQL inconsistente – como você mesmo pode ver no teu exemplo abaixo.

    Além disso, quanto mais features e mais extensões no T-SQL, mais complexo o query optimizer ficava, tonando-se mais lento. Esse componente foi redesenhado para fazer bem apenas o que ele realmente deve fazer. Alguma pessoas dizem que o produto ficou mais difícil de ser usado com essas regras mais rigidas, na minha opnião (e me desculpe o palavreado) ele ficou menos “a prova de idiota” J

    Veja os exemplos que você indicou abaixo... por mais que o produto funcione de um jeito ou de outro, as best-practices ditam que deve-se sempre especificar o column-list, e não se deve usar o SELECT *, ou seja, seu desenvolvedor está produzindo código de má qualidade – fato!

    Existe um documento que trata das incompatibilidades da versão 2005 com 2000, talvez você encontre aí o que procura:

    Discontinued Database Engine Functionality in SQL Server 2005

    http://msdn.microsoft.com/en-US/library/ms144262(v=sql.90).aspx

    Além desse, de uma olhada num desses outros documentos:

    http://msdn.microsoft.com/en-us/library/ms143729(v=sql.90).aspx

    http://msdn.microsoft.com/en-US/library/ms143179(v=sql.90).aspx

    http://msdn.microsoft.com/en-US/library/ms143359(v=sql.90).aspx

    Cada um desses documentos tem versões pro 2008, 2008 R2 e 2012. Como não existe migration path entre 2000 e 2012, o documento do SQL 2012 não deve citar as mudanças que ocorreram a partir do 2000, e sim as mudanças a partir do 2005.

    []s

    João Polisel

    Sem comentários.


    Wolney


    quinta-feira, 28 de março de 2013 21:49

Todas as Respostas

  • Wolkey,

    Cuidado!, falta de atenção, veja que o erro acontece em todas as execução e não de forma esporadica conforme falado.

    A tabela resumo possui 5 coluna enquanto a tabela vendas apenas 4, então os 2 inserts (Com ou ser order by) dão erro uma vez que o nome das colunas no insert não foi especificado, então o SQL Server entende que todas as 5 colunas serão preenchidas enquanto o select retorna apenas 4.

    Mesmo o comando com order by da erro:

    insert into resumo 
    select * from vendas
    order by 1
    Msg 213, Level 16, State 1, Line 1
    Column name or number of supplied values does not match table definition.


    Fabrizzio A. Caputo
    MCT
    Certificações:
    Oracle OCA 11g
    MCITP SQL Server 2008 Implementation and Maintenance
    MCITP SQL Server 2008 Developer
    ITIL V3 Foundation
    Blog Pessoal: www.fabrizziocaputo.wordpress.com
    Twitter: @FabrizzioCaputo
    Email: fabrizzio.antoniaci@gmail.com


    terça-feira, 26 de março de 2013 18:51
    Moderador
  • Execute apenas este script e vera que o erro tambem acontece:

    create table Resumo (id int , nome varchar(10), valor int, usuario varchar(10) , fake int  )
    Create table vendas (id int, nome varchar(10), valor int, usuario varchar(10))
    insert into  vendas (id, nome, valor, usuario )
    values (1,'jose', 10, 'ze')
    /*
    Tanto no INSERT como no SELECT não foram declaradas as colunas
    Na tabele RESUMO temos 5 colunas. Na tabela VENDAS, temos 4 colunas.
    Fazendo o comando abaixo com ORDER BY, comando executado com sucess. 
    */
    insert into resumo 
    select * from vendas
    order by 1
    


    Fabrizzio A. Caputo
    MCT
    Certificações:
    Oracle OCA 11g
    MCITP SQL Server 2008 Implementation and Maintenance
    MCITP SQL Server 2008 Developer
    ITIL V3 Foundation
    Blog Pessoal: www.fabrizziocaputo.wordpress.com
    Twitter: @FabrizzioCaputo
    Email: fabrizzio.antoniaci@gmail.com

    terça-feira, 26 de março de 2013 18:53
    Moderador
  • Fabrizzio,

    Desculpe, acho que não fui claro no email.

    A primeira execução foi feita no ambiente com SQL 2000. Neste ambiente a execução com order by executa com sucesso. Já na segunda execução sem o order by, da o erro.

    Na outro execução no SQL 2000, tanto com order by como sem o order by da o erro.

     


    Wolney

    terça-feira, 26 de março de 2013 18:55
  • Wolney,

    Agora sim ficou claro, e é verdade, realmente executa, ele mapea a coluna 1 do select para a coluna 1 da tabela do insert, porem como temos 5 colunas disponiveis para 4 valores ele deixa a ultima em branco. No SQL Server 2000 para o 2005+ temos varias diferenças, eu sinceramente não sabia desta.

    Outra diferença que conheco é, execute a query abaixo sobre suas tabelas no 2000 e no 2005 ou superior. No 2000 ele executa sem problemas, em 2005 ou superior ele da erro falando que a coluna é ambigua, sinceramente não temos muito o que fazer, arrume seu processo e especifique as colunas no insert.

    Tentei com a base nivel 80 e o mesmo erro é gerado, portando funcionara apenas no sql server 2000 mesmo!

    select Id, * from vendas
    order by id
    Estou buscando algo na internet mas ainda sem sucesso, sinceramente nunca tinha visto isso e desconhecia este comportamento. Qualquer coisa que encontrar posto aqui.


    Fabrizzio A. Caputo
    MCT
    Certificações:
    Oracle OCA 11g
    MCITP SQL Server 2008 Implementation and Maintenance
    MCITP SQL Server 2008 Developer
    ITIL V3 Foundation
    Blog Pessoal: www.fabrizziocaputo.wordpress.com
    Twitter: @FabrizzioCaputo
    Email: fabrizzio.antoniaci@gmail.com

    terça-feira, 26 de março de 2013 19:05
    Moderador
  • Wolney, boa tarde.

    Em qualquer insert como origem um select, SEMPRE especifique os nomes das colunas. Isto vai te livrar de muitas futuras dores de cabeça.

    Abs.


    Eduardo Gomes - http://www.h1solucoes.com.br - Twitter: @edugp_sp

    terça-feira, 26 de março de 2013 19:24
  • Wolney, boa tarde.

    Em qualquer insert como origem um select, SEMPRE especifique os nomes das colunas. Isto vai te livrar de muitas futuras dores de cabeça.

    Abs.


    Eduardo Gomes - http://www.h1solucoes.com.br - Twitter: @edugp_sp

    Olá Eduardo,

    Com certeza!!! É isso que nós DBA do DataCenter da Imprensa Oficial passamos como boas práticas para os desenvolvedores e consultores que trabalham aqui.

    Acontence que passamos 32 bancos de dados de dois servidores com SQL 2000 para um servidor com SQL 2008 neste final de semana.  Acontence que um sistema com quase 10 anos de uso, começou a apresentar problemas e falaram que era motivo da migração.

    Passamos a orientação em como corrigir.

    Agora preciso achar no site da Microsoft algum  KB que justifique essa mudança de comportamento.

    Talvez um FIX que era para colocar no 2000  e no 2008 foi corrigido.... enfim.

    Já vi os links abaixo antes de realizarmos a migração e passamos como orientação para os desenvolvedores.

    http://msdn.microsoft.com/pt-br/library/ms143729(v=sql.100).aspx

    http://msdn.microsoft.com/pt-br/library/bb510662(v=SQL.100).aspx


    Wolney

    terça-feira, 26 de março de 2013 19:37
  • /*
    Sem nome das colunas, ocorre o erro relatado acima
    */
    insert into resumo  
    select * from vendas
    order by 1
    
    /*
    Declarando-se o nome das colunas, o insert é realizado corretamente.
    */
    insert into resumo (id,nome,valor,usuario)
    select * from vendas
    order by 1


    Não pude testar o SQL 2000, mas esse modo de inserção citado no primeiro exemplo é confuso e impreciso (*) e se foi realmente um comportamento removido (única coisa que pensei no momento, rs), parece ser por incentivar a  má prática do "não uso de colunas (critério)" seja no select e/ou no insert,  algo que a MS vem amadurecendo no produto ao passar dos anos.

    []


    terça-feira, 26 de março de 2013 21:32
  • Somente para deixar registrado mais um comentário sobre o assunto. A resposta foi feito pelo João Bosel Polisel que faz parte do grupo MSSQL-L do Yahoo Groups.

    De: mssql-l@yahoogrupos.com.br [mailto:mssql-l@yahoogrupos.com.br] Em nome de João Polisel
    Enviada em: quarta-feira, 27 de março de 2013 16:18
    Para: mssql-l@yahoogrupos.com.br
    Assunto: RE: [mssql-l] INSERT com SELECT. As vezes executa com sucesso, as vezes da a mensagem "Column name or number of supplied values does not match table definition." SQL 2000

    Wolney,

    Não creio que haja um KB falando disso, mas é verdade que o SQL 2000 era “uma mãe” para consertar erros de desenvolvimento em runtime e isso foi removido a partir do 2005.

    A filosofia do produto teve que mudar, porque por mais que se fizesse não há como você prever, detectar e corrigir todos os erros e inconsistências no código, e isso tornava o comportamento do SQL inconsistente – como você mesmo pode ver no teu exemplo abaixo.

    Além disso, quanto mais features e mais extensões no T-SQL, mais complexo o query optimizer ficava, tonando-se mais lento. Esse componente foi redesenhado para fazer bem apenas o que ele realmente deve fazer. Alguma pessoas dizem que o produto ficou mais difícil de ser usado com essas regras mais rigidas, na minha opnião (e me desculpe o palavreado) ele ficou menos “a prova de idiota” J

    Veja os exemplos que você indicou abaixo... por mais que o produto funcione de um jeito ou de outro, as best-practices ditam que deve-se sempre especificar o column-list, e não se deve usar o SELECT *, ou seja, seu desenvolvedor está produzindo código de má qualidade – fato!

    Existe um documento que trata das incompatibilidades da versão 2005 com 2000, talvez você encontre aí o que procura:

    Discontinued Database Engine Functionality in SQL Server 2005

    http://msdn.microsoft.com/en-US/library/ms144262(v=sql.90).aspx

    Além desse, de uma olhada num desses outros documentos:

    http://msdn.microsoft.com/en-us/library/ms143729(v=sql.90).aspx

    http://msdn.microsoft.com/en-US/library/ms143179(v=sql.90).aspx

    http://msdn.microsoft.com/en-US/library/ms143359(v=sql.90).aspx

    Cada um desses documentos tem versões pro 2008, 2008 R2 e 2012. Como não existe migration path entre 2000 e 2012, o documento do SQL 2012 não deve citar as mudanças que ocorreram a partir do 2000, e sim as mudanças a partir do 2005.

    []s

    João Polisel

    Sem comentários.


    Wolney


    quinta-feira, 28 de março de 2013 21:49