none
Compreensão de lógica para registro no banco de dados RRS feed

  • Pergunta

  • Olá!

    Meu problema é mais voltado à lógica do que sintaxe. O que eu preciso é o seguinte: tenho uma tabela de clientes e uma de serviços. Para cada vez que for registrar uma informação para determinado cliente, ele gera um incremento. Porém, ao registrar informação, eu preciso que comece a partir do número 1 para cada cliente registrado. Por exemplo, tenho um cliente X e um Y. Farei três registros do cliente X. Gerará num dos campos o registro 1, 2 e 3, os quais estão atrelados ao cliente X. Agora farei dois registros do cliente Y. Terá que gerar no mesmo campo do anterior, mas começando em 1 e prosseguindo com 2, 3, 4, etc. Quando for consultar, será consultado com um "select * from servicos where cliente_idCliente = @idClienteX", por exemplo. Assim, retornará com os valores somente dele.

    Alguém tem alguma ideia do que possa ser feito?

    segunda-feira, 16 de julho de 2012 19:11

Todas as Respostas

  • Olá,

    Me confirme se é isso....

    Você tem os cliente JOAO e MARIO. Daí você cria os serviços conforme abaixo:

    1 - JOAO

    2 - JOAO

    1 - MARIO

    3 - JOAO

    2 - MARIO

    Os próximos registros seriam 4 - JOAO e 3 - MARIO. É isso? Ter um sequencial por cliente que faz o serviço?


    Marco Antônio Pinheiro / MCTS - MCC http://marcoantoniopinheiro.blogspot.com

    segunda-feira, 16 de julho de 2012 21:23
  • Olá,

          A solução neste caso é utilizar uma trigger que irá monitorar a inclusão/Alteração, já que a opção do contador é reiniciar a cada cliente. Se este campo incremental for somente para fins de identificação, tipo, a primeira alteração do cliente, a segunda, a terceira e assim por diante... Talvez a melhor opção seja utilizar as funções de ranqueamento do SQL Server 2005 em diante, mais especificamente a ROW_NUMBER() em conjunto com uma data de inclusão do registro.


    Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008


    CREATE DATABASE Exemplo
    GO
    USE Exemplo
    go
    CREATE TABLE Clientes
    (CodigoCliente INT IDENTITY,
    Nome VARCHAR(40))
    CREATE TABLE Servicos
    (CodigoCliente INT,
    CodigoServico INT,
    DataServico DATETIME DEFAULT GETDATE(),
    ValorServico MONEY DEFAULT 0)
    ;ALTER TRIGGER trgClientes 
    ON Clientes
    FOR INSERT, UPDATE
    as 
        DECLARE @CodigoServico INT = 0
        SET @CodigoServico =ISNULL((SELECT MAX(Servicos.CodigoServico)+1 FROM Servicos WHERE Servicos.CodigoCliente = (SELECT INSERTED.CodigoCliente FROM INSERTED)), 1)
        INSERT INTO servicos
        
        SELECT INSERTED.CodigoCliente, @CodigoServico, GETDATE(), 0 
          FROM INSERTED 
          
          
    INSERT INTO Clientes (Nome) VALUES ('Roberto Fonseca')      
    SELECT * FROM clientes
    SELECT * FROM Servicos -- O Contador inicia em 1
    INSERT INTO Clientes (Nome) VALUES ('Maria da Silva')
    SELECT * FROM clientes
    SELECT * FROM Servicos -- O Contador inicia em 1
    UPDATE Clientes SET nome = 'Marisa da Silva' WHERE codigocliente = 2 -- Nome Alterado de Maria para Marisa
    SELECT * FROM clientes
    SELECT * FROM Servicos -- O Contador incrementa para 2 por causa da alteração de nome.
    TRUNCATE TABLE clientes
    TRUNCATE TABLE servicos
    go
    USE master
    go
    DROP DATABASE Exemplo
    GO

    segunda-feira, 16 de julho de 2012 23:14
    Moderador
  • A ideia é exatamente a qual o Marco Antonio falou. 

    Roberto, esse trecho seria com uma funcionalidade similar ao mencionado pelo Marco Antonio?

    terça-feira, 17 de julho de 2012 13:02
  • Uma outra forma de implementar seria com o exemplo abaixo:

    create table clientes (cod_cli int, nome varchar(50))

    create table servico (cod_serv int, cod_cli int)

    insert into clientes values (1, 'JOAO')
    insert into clientes values (2, 'MARIO')

    insert into servico values (1, 1)
    insert into servico values (2, 1)
    insert into servico values (3, 2)
    insert into servico values (4, 2)
    insert into servico values (5, 1)

    Na tabela SERVICO o código sequencial da tabela não seria significante, ou seja, fisicamente não ficaria da forma desejada. Você irá fazer este sequencial desejado com a consulta abaixo:

    select ROW_NUMBER() OVER (PARTITION BY c.nome ORDER BY c.nome) AS codigo, nome
    from servico s, clientes c
    where s.cod_cli = c.cod_cli

    Esta é uma outra forma de atender ao que foi pedido. Mas claro, vai depender de N condições pra entrar em produção.

    Uma vantagem que vejo neste exemplo é que serve tanto para SQL como para Oracle.


    Marco Antônio Pinheiro / MCTS - MCC http://marcoantoniopinheiro.blogspot.com

    terça-feira, 17 de julho de 2012 13:17
  • Mas desta forma, além de estar passando um valor - o que não é o ideal, não estaria fazendo da forma esperada. A sua lógica estava certa, mas fazendo o teste de mesa com esses inserts sai um resultado totalmente diferente. Veja só, você colocou para o cliente com ID 1 os IDs de serviços 1, 2 e 5 e para o cliente ID 2, os serviços 3 e 4. Eu preciso que, ao inserir um novo registro do cliente ID 1, por exemplo, fosse na sequência 3. 

    Estive pensando agora, pode até ser meio que bobeira, mas poderia, por exemplo, criar uma SP que fizesse o seguinte:

    create procedure sp_RegCliente
    -- Recebe o ID do cliente como parâmetro de valor
    @idClientePJ integer
    as
    begin
    	-- Declara uma variável que receberá o próximo registro
    	declare @proximoReg integer
    	-- Ajusta o valor para que receba o próximo ID de serviço conforme o cliente,
    	-- caso não tenha registro, a consulta retorna zero, então colocado +1, então assume
    	-- o valor 1
    	set @proximoReg = (select COUNT(*) from ClientesPJ where idClientePJ=@idClientePJ) + 1
    	-- Insere os dados conforme a tabela
    	insert into Servico(idServico, idClientePJ) values
    	(@proximoReg, @idClientePJ)
    	-- Retorna para a aplicação o valor gerado
    	return @proximoReg
    end
    go

    Espero que funcione...

    • Editado Matheus Gelinski terça-feira, 17 de julho de 2012 14:23 Inserção de código com proposta de solução
    terça-feira, 17 de julho de 2012 14:11
  • Matheus,

          Seria um resultado semelhante, porém utilizando uma ferramenta automática do SQL Server.

          Como eu não sabia o seu objetivo, tentei fazer um exemplo utilizando as duas tabelas, mas você pode fazer isso utilizando uma única tabela.

          Eu revisaria o design da sua base, porque para mim, não faz sentido você ter vários registros de um mesmo cliente. O mais importante, você terá que ter uma chave primária, mas pelo que entendi vc quer ter uma sequencia de valores para um mesmo cliente... Como você vai identificar um cliente? Pelo nome? E se alguém alterar o nome? Perde a referencia?


    Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008

    quarta-feira, 18 de julho de 2012 01:59
    Moderador
  • Eu vou reconhecer o cliente pelo seu ID. O registro específico, através da consulta:

    "select * from Servicos join ClientesPJ on Servicos.idClientePJ = ClientesPJ.idClientePJ where Servicos.idClientePJ = @idClientePJ and Servicos.idServico = @idServico"

    A chave primária será idOperacao, onde está como IDENTITY(1,1). Entendeu?

    quinta-feira, 19 de julho de 2012 12:07