none
View contando numero de inscrições RRS feed

  • Pergunta

  • Olá,

    Tenho duas tabelas TB_Evento (id_evento, nome_evento, limitacao_inscricao) e TB_Inscricao (id_inscricao, id_evento, nome_incrito).

    Diante dessa pandemia, a quantidade de inscrições estão sendo limitada nos eventos. Foi solicitado a adição de um campo [limitacao_inscricao] na tabela de eventos. Ao inserir um evento, tem que preencher com um número específico para cada evento.

    Gostaria de criar uma view que contasse a quantidade de registros das pessoas que foram inscritas em um dos eventos (os eventos tem quantidades diferentes de limitações. Depende do tamanho da sala). Ou seja, o campo [limitacao_evento] servirá de parâmetro para mostrar a quantidade de linhas de acordo com o evento.

    Não sei se fui claro.

    Agradeço,


    Sam


    • Editado Samfera terça-feira, 27 de outubro de 2020 02:20
    terça-feira, 27 de outubro de 2020 02:19

Respostas

  • Como você executou o Insert?

    Revendo a query do Exists percebi um problema no Having, já que o gatilho é After Insert e está somando de novo as linhas as linhas inseridas, mas isso deveria fazer com que a inserção não fosse permitida mesmo abaixo do limite, e não deveria permitir de qualquer forma inserção acima do limite. Fiz algums alterações relativas a esse problema e também para acrescentar mais informações na mensagem:

    ALTER TRIGGER [dbo].TB_InscricaoAfterInsert ON [dbo].TB_Inscricao  
    AFTER INSERT  
    AS  
    
    declare @id_evento int;
    declare @limite int;
    declare @inscricoes int;
    
    SELECT TOP(1)
        @id_evento = c.id_evento, 
        @limite = e.limitacao_inscricao, 
        @inscricoes = count(1)
    FROM 
    (
        select distinct id_evento from inserted
    ) as c
    inner join TB_Evento as e
        on e.id_evento = c.id_evento
    inner join TB_Inscricao as i
        on i.id_evento = e.id_evento   
    group by c.id_evento, e.limitacao_inscricao
    having e.limitacao_inscricao < count(1);
    
    IF @id_evento is not null 
      BEGIN  
        RAISERROR
            ('Quantidade de inscrições (%d) acima do limite (%d) do evento (%d)', 
             16, 
             1,
             @inscricoes,
             @limite,
             @id_evento);  
        ROLLBACK TRANSACTION;  
        RETURN   
      END;  
    GO

    Experimente executar uns Inserts através do SQL Server Management Studio e verifique se é exibida alguma mensagem. As inserções são canceladas quando o Rollback é executado. Se você conseguir inserir novas linhas em eventos acima do limite, experimente deixar o Raiserror antes do If só para ver as quantidades que serão exibidas na mensagem e verificar o que está ocorrendo.

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    • Marcado como Resposta Samfera sexta-feira, 30 de outubro de 2020 19:43
    sexta-feira, 30 de outubro de 2020 18:39

Todas as Respostas

  • Bom dia,

    Não sei se entendi corretamente a sua questão mas segue uma sugestão para testes:

    select e.id_evento, e.nome_evento, e.limitacao_inscricao, count(1) as quantidade_inscritos
    from TB_Evento as e
    inner join TB_Inscricao as i
        on i.id_evento = e.id_evento
    group by e.id_evento, e.nome_evento, e.limitacao_inscricao

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    terça-feira, 27 de outubro de 2020 12:34
  • Obrigado pela resposta, gapimex.

    A view funcionará como um gatilho pra não permitir mas inscrição. O campo [limitacao_inscricao] será o parâmetro pra essa limitação. O resultado da view que você mandou ficou assim:

    Id_evento     nome_evento     limitacao_inscricao   quantidade_inscritos
    1                  Eve1                           30                          37
    2                  Eve2                           40                          51
    3                  Eve3                           20                          33

    Veja que nos exemplos que temos, tem mais inscritos do que deveria.

    Deu pra entender?

    Meio louco isso

    Mais uma vez, obrigado.


    Sam

    terça-feira, 27 de outubro de 2020 14:53
  • Segue um exemplo de código para criação do gatilho:

    CREATE TRIGGER [dbo].TB_InscricaoAfterInsert ON [dbo].TB_Inscricao  
    AFTER INSERT  
    AS  
    with CTE_CountInserts as
    (
        select id_evento, count(1) as quantidade_inserts
        from inserted
        group by id_evento
    )
    
    IF EXISTS 
        (SELECT c.id_evento
         FROM CTE_CountInserts as c
         inner join TB_Evento as e
             on e.id_evento = c.id_evento
         inner join TB_Inscricao as i
             on i.id_evento = e.id_evento   
         group by c.id_evento
         having e.limitacao_inscricao < count(1) + c.quantidade_inserts)
    BEGIN  
    RAISERROR ('Quantidade de inscrições acima do limite do evento', 16, 1);  
    ROLLBACK TRANSACTION;  
    RETURN   
    END;  
    GO  

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    terça-feira, 27 de outubro de 2020 18:07
  • Mais uma vez, obrigado pela resposta, gapimex.

    Rodei a query mas apresentou o seguinte erro:

    Msg 156, Nível 15, Estado 1, Procedimento TB_InscricaoAfterInsert, Linha 11 [Linha de Início do Lote 0]
    Sintaxe incorreta próxima à palavra-chave 'IF'.

    Até tentei dar seguimento, mas não tive sucesso.



    Sam

    terça-feira, 27 de outubro de 2020 20:53
  • Não testei mas talvez seja a CTE antes do If. Experimente essa outra versão:

    CREATE TRIGGER [dbo].TB_InscricaoAfterInsert ON [dbo].TB_Inscricao  
    AFTER INSERT  
    AS  
    IF EXISTS 
        (SELECT c.id_evento
         FROM 
         (
             select id_evento, count(1) as quantidade_inserts
             from inserted
             group by id_evento
         ) as c
         inner join TB_Evento as e
             on e.id_evento = c.id_evento
         inner join TB_Inscricao as i
             on i.id_evento = e.id_evento   
         group by c.id_evento
         having e.limitacao_inscricao < count(1) + c.quantidade_inserts)
    BEGIN  
    RAISERROR ('Quantidade de inscrições acima do limite do evento', 16, 1);  
    ROLLBACK TRANSACTION;  
    RETURN   
    END;  
    GO  

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    quarta-feira, 28 de outubro de 2020 12:12
  • É meu amigo... Não deu certo.

    Continua com erro.

    Msg 8121, Nível 16, Estado 1, Procedimento TB_InscricaoAfterInsert, Linha 17 [Linha de Início do Lote 0]
    A coluna 'TB_Evento.limitacao_inscricao' é inválida na cláusula HAVING porque não está contida em uma função de agregação nem na cláusula GROUP BY.
    Msg 8121, Nível 16, Estado 1, Procedimento TB_InscricaoAfterInsert, Linha 17 [Linha de Início do Lote 0]
    A coluna 'c.quantidade_inserts' é inválida na cláusula HAVING porque não está contida em uma função de agregação nem na cláusula GROUP BY.

    Fiquei tentando uma solução, mas nada. Ainda sou novato no SQL (rs).

    Obrigado novamente

    Sam

    quinta-feira, 29 de outubro de 2020 22:27
  • Tente acrescentar as 2 colunas das mensagens de erro no Group By:

    CREATE TRIGGER [dbo].TB_InscricaoAfterInsert ON [dbo].TB_Inscricao  
    AFTER INSERT  
    AS  
    IF EXISTS 
        (SELECT c.id_evento
         FROM 
         (
             select id_evento, count(1) as quantidade_inserts
             from inserted
             group by id_evento
         ) as c
         inner join TB_Evento as e
             on e.id_evento = c.id_evento
         inner join TB_Inscricao as i
             on i.id_evento = e.id_evento   
         group by c.id_evento, c.quantidade_inserts, e.limitacao_inscricao
         having e.limitacao_inscricao < count(1) + c.quantidade_inserts)
    BEGIN  
    RAISERROR ('Quantidade de inscrições acima do limite do evento', 16, 1);  
    ROLLBACK TRANSACTION;  
    RETURN   
    END;  
    GO  

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    sexta-feira, 30 de outubro de 2020 12:49
  • Dessa vez não apresentou nenhum erro. Contudo, ao fazer uma nova inscrição (além da quantidade limitada), ele permitiu.

    Me diga uma coisa: 
    A mensagem abaixo aparece onde? Deveria bloquear a inscrição além da permitida? Ou só informativa?
    RAISERROR ('Quantidade de inscrições acima do limite do evento', 16, 1); 


    Mais uma vez obrigado. 

    Sam

    sexta-feira, 30 de outubro de 2020 15:55
  • Como você executou o Insert?

    Revendo a query do Exists percebi um problema no Having, já que o gatilho é After Insert e está somando de novo as linhas as linhas inseridas, mas isso deveria fazer com que a inserção não fosse permitida mesmo abaixo do limite, e não deveria permitir de qualquer forma inserção acima do limite. Fiz algums alterações relativas a esse problema e também para acrescentar mais informações na mensagem:

    ALTER TRIGGER [dbo].TB_InscricaoAfterInsert ON [dbo].TB_Inscricao  
    AFTER INSERT  
    AS  
    
    declare @id_evento int;
    declare @limite int;
    declare @inscricoes int;
    
    SELECT TOP(1)
        @id_evento = c.id_evento, 
        @limite = e.limitacao_inscricao, 
        @inscricoes = count(1)
    FROM 
    (
        select distinct id_evento from inserted
    ) as c
    inner join TB_Evento as e
        on e.id_evento = c.id_evento
    inner join TB_Inscricao as i
        on i.id_evento = e.id_evento   
    group by c.id_evento, e.limitacao_inscricao
    having e.limitacao_inscricao < count(1);
    
    IF @id_evento is not null 
      BEGIN  
        RAISERROR
            ('Quantidade de inscrições (%d) acima do limite (%d) do evento (%d)', 
             16, 
             1,
             @inscricoes,
             @limite,
             @id_evento);  
        ROLLBACK TRANSACTION;  
        RETURN   
      END;  
    GO

    Experimente executar uns Inserts através do SQL Server Management Studio e verifique se é exibida alguma mensagem. As inserções são canceladas quando o Rollback é executado. Se você conseguir inserir novas linhas em eventos acima do limite, experimente deixar o Raiserror antes do If só para ver as quantidades que serão exibidas na mensagem e verificar o que está ocorrendo.

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    • Marcado como Resposta Samfera sexta-feira, 30 de outubro de 2020 19:43
    sexta-feira, 30 de outubro de 2020 18:39
  • Bingo!!!

    Funcionou direitinho. O SQL me retornou a mensagem.

    Muito obrigado pela ajuda. 


    Só mais um coisa:

    Se eu quisesse apenas que ele contasse e comparasse com o o valor do [limitacao_inscricao] mas que não acionasse nenhum gatilho. Poderia usar apenas o select + o having? Eu nunca usei o having. 

    Te agradeço d+ pela ajuda.


    Sam

    sexta-feira, 30 de outubro de 2020 19:43
  • Você pode utilizar aquela primeira consulta que sugeri, e se preferir pode acrescentar o Having, que é utilizado quando o filtro contem uma função de agregação, que no caso seria a função Count.

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    sexta-feira, 30 de outubro de 2020 20:12
  • Certo.

    Vou tentar pra ver se funciona.

    mais uma vez, obrigado.


    Sam

    sexta-feira, 30 de outubro de 2020 20:14