none
Insert em massa para dentro de uma tabela RRS feed

  • Pergunta

  • Tenho duas proc's que o meu sistema em VB já utiliza. Uma para Insert e outra para Update. Preciso usá-la agora, direto no banco. A tabela de destino possui uma chave composta, da seguinte forma. Um campo chamado ID_OIT_LET e outro campo chamado ID_OIT. O ID_OIT ele é único, nunca se repete. O campo ID_OIT_LET, ele só recebe 1, 2 ou 3. Quando ele recebe os três valores, aí eu tenho 3 vezes o mesmo valor em ID_OIT, assim:

    ID_OIT_LET ID_OIT


    1 ------------------ 39510

    1 ------------------ 39511

    1 ------------------ 39517

    2 ------------------ 39517

    3 ------------------ 39517

    Na tabela origem, eu tenho o ID_OIT e os campos a serem populados, que é um campo data e um varchar. Quanto ao ID_OIT_LET posso fazer o insert três vezes para gerar os valores 1,2 e 3. A minha dúvida é fazer uma espécie loop na tabela origem, para que ela vá pegando o valor e inserindo. E tem mais um problema. caso já exista aquela chave no banco, então deve-se chamar a PROC de Update e não a de Insert. Gostaria de uma ajuda, para me mostrarem qual caminho tomar. Tô meio sem idéia de como fazer. espero ter sido claro.

    quinta-feira, 20 de abril de 2017 12:19

Todas as Respostas

  • Se o campo  ID_OIT nunca se repete, pra que você tem uma chave composta?
    quinta-feira, 20 de abril de 2017 12:47
  • Deleted
    quinta-feira, 20 de abril de 2017 14:08
  • Eu vim fazer um trampo de cinco dias. Como foi feito, não sei. mas se repete sim, informei errado. Ele repete, quando insiro 2 ou 3 registros para mesmo paciente nessa tabela, vide imagem. Mas como foi feito no passado, realmente não sei. Só quero gerar esse insert, terminei as outras tarefas, apontar minhas horas e esperar o grande e glorioso dia do depósito em minha conta, ehehehehehe.

    Desculpe-me pela informação equivocada, o ID_OIT pode sim, se repetir. Não muitas vezes, mas acontece sim. Valeu cara.

    quinta-feira, 20 de abril de 2017 16:15
  • José Diz, só me ajuda no seguinte. Vi que na tabela origem(Planilha_Origem), não tenho o campo ID_OIT. A tabela ID_OIT se relaciona com a tabela EXAME_REALIZADO pelo campo ID_EXM_REA. A tabela EXAME_REALIZADO se relaciona com a tabela planilha_leitura(origem)  pelo campo ID_XFC. Criei a coluna ID_OIT na tabela origem(planilha_leitura ) e agora preciso popular essa tabela com os ID_OIT, algo parecido com isso, só que esse select não é possível:

    update t_cmo_planilha_leitura set id_oit = (select oit.id_oit from oit1980 oit
     inner join Exame_Realizado er on oit.id_exm_rea = er.id_exm_rea
     inner join planilha_leitura ef on er.id_xfc = ef.id_xfc)

    Preiso fazer um UPD que atualize todos os registros de uma vez. Como faço isso?

    quinta-feira, 20 de abril de 2017 17:12
  • Resolvi assim esse update:

    update t_cmo_planilha_leitura set id_oit = oit.id_oit from t_cmo_oit1980 oit
     inner join t_cmo_Exame_Realizado er on oit.id_exm_rea = er.id_exm_rea
     inner join t_cmo_planilha_leitura ef on er.id_xfc = ef.id_xfc

    quinta-feira, 20 de abril de 2017 17:22
  • Esse UPD que eu fiz, não populou todos os registros, somente 573 dos 1009. O que pode ter acontecido?
    quinta-feira, 20 de abril de 2017 17:46
  • Fiz esse insert, conforme o colega José Diz me orientou:

    declare @UDT table (Num int);
    INSERT into @UDT values (1), (2), (3);
    
    SELECT T2.Num, T1.ID_OIT, T1.DT_RX, T1.RX_NUM
      from t_cmo_planilha_leitura as T1
           cross join @UDT as T2;
    
    with cteComb as (
    SELECT T2.Num, T1.ID_OIT, T1.DT_RX, T1.RX_NUM
      from t_cmo_planilha_leitura as T1
           cross join (values (1), (2), (3)) as T2 (Num)
    )
    MERGE
      into #t_cmo_oit1980_leitura_temp1 as D
      using cteComb as O
      on D.ID_OIT_LET = O.Num and D.ID_OIT = O.ID_OIT
      when matched then
           UPDATE set DT_RX= O.DT_RX, RX_NUM= O.RX_NUM
      when not matched by target then
           INSERT (ID_OIT_LET, ID_OIT, DT_RX, RX_NUM)
             values (O.Num, O.ID_OIT, O.DT_RX, O.RX_NUM) 
    ;

    O que passa é que, se a tabela está vazia, ele insere normalmente(fiz com uma temp para testes), mas se a tabela tem informação, que no caso tem 8068 registros, não acrescenta nada e me dá essa mensagem:

    (3 linha(s) afetadas)

    (3027 linha(s) afetadas) Mensagem 8672, Nível 16, Estado 1, Linha 104 The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.

    Como proceder?


    quinta-feira, 20 de abril de 2017 19:18
  • Porque você não gera o Cursor preenchendo as 3 linhas? 

    Tente fazer um teste com esse exemplo de cursor.

    SET NOCOUNT ON
    
    DECLARE 
    	@tp_data VARCHAR(10),
    	@tp_cliente INT,
    	@tp_nickname CHAR(12),
    	@tp_nome VARCHAR(7),
    	@tp_hora DATETIME,
    	@tp_teste1 VARCHAR(80),
    	@tp_teste2 INT,
    	@Contador INT
    
    DECLARE C1 CURSOR 
    FOR 
    	SELECT 	*
    	FROM TESTE_TB WITH (NOLOCK)	
    	WHERE teste2 = 0
    
    OPEN C1
    
    FETCH C1
    INTO		@tp_data,@tp_cliente,@tp_nickname,@tp_nome,@tp_hora,@tp_teste1,@tp_teste2
    
    WHILE @@FETCH_STATUS = 0
    	BEGIN
    		SELECT @Contador = @Contador + 1
    		PRINT 'Execucao ' + Convert(Varchar(5), @Contador) + ' - ' + @tp_nickname
    	
    		/*
    		CONTROLE PARA INSERIR AS 3 LINHAS
    		*/ 
    	
    		FETCH C1
    		INTO		@tp_data,@tp_cliente,@tp_nickname,@tp_nome,@tp_hora,@tp_teste1,@tp_teste2
    	END
    CLOSE C1
    DEALLOCATE C1 
    

    • Sugerido como Resposta Junior Galvão - MVPMVP quinta-feira, 20 de abril de 2017 22:59
    • Marcado como Resposta Robson William Silva segunda-feira, 24 de abril de 2017 12:06
    • Não Marcado como Resposta pnet segunda-feira, 24 de abril de 2017 15:14
    quinta-feira, 20 de abril de 2017 20:03
  • Deleted
    quinta-feira, 20 de abril de 2017 21:18
  • Você está certo. É isso mesmo, as relações diretas. Vi que a tabela OIT1980 funciona como uma tabela associativa entre a EXAME_REALIZADO  e a OIT1980_LEITURA. Preciso gerar primeiro a chave ID_OIT na tabela OIT1980, e a chave eu preciso relacionar o ID_EXM_REA baseado no ID_XFC(Paciente) e no campo ID_OIT eu dou um MAX(ID_OIT_ + 1. Preciso fazer isso, mas que a query vai percorrendo as tabelas Exame_Realizado e comparando com a Planilha_Leitura(pegando os ID_XFC) e ir adicionando na tabela OIT1980 conforme regra acima. O colega José Carvalheira citou fazer um cursor, é o melhor caminho? 
    segunda-feira, 24 de abril de 2017 11:06
  • set nocount on
    declare 
    @id_xfc int,
    @id_exm_rea int,
    @id_oit int
    
    declare exame_cur cursor
     for
     select distinct er.id_exm_rea from t_cmo_Exame_Realizado er 
     inner join t_cmo_planilha_leitura pl on er.ID_XFC = pl.ID_XFC
     inner join t_cmo_exame ex on er.id_exm = ex.ID_EXM
     where er.id_exm = 3936 and pl.NO_EXM = 'TÓRAX: P.A.' and er.NO_RX in(select pl.RX_NUM from t_cmo_planilha_leitura pl)
     order by er.id_exm_rea
    
     open exame_cur
     fetch next from exame_cur into @id_exm_rea
    
     select max(id_oit) as id_oit into t_id_oit_1 from t_cmo_oit1980
    
     --insert into t_cmo_oit1980_temp1(id_oit) select id_oit from t_id_oit_1
    
     while @@fetch_status = 0
     begin
        insert into t_cmo_oit1980_temp1
        select
        (select id_oit + 1 from t_cmo_oit1980_temp1),
        (@id_exm_rea)
    
     end
    
     CLOSE exame_cur
     DEALLOCATE exame_cur
    
    select * from t_cmo_oit1980_temp1
    go

    Meu código acima está correto?

    Atualizei o código para o acima, e ao executar está demorando bastante. Postei essas linhas e ainda não terminou. Já vai mais de 2 minutos

    segunda-feira, 24 de abril de 2017 16:18
  • Está demorando demais e não carrega nada. O que eu quero é só gerar registros na tabela oit1980, gerando o id_oit(PK) que é max + 1 e inserir para cada id o id_exm_rea, que é o que vem do cursor. Agora se houvesse outra forma de inserir, sem a necessidade do cursor, ficaria feliz.
    segunda-feira, 24 de abril de 2017 16:31
  • Entrou em loop infinito e repetiu o mesmo registro quase 1 milhão de vezes.
    segunda-feira, 24 de abril de 2017 16:55