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 / 124798
Accepted
Nelson
Nelson
Asked: 2015-12-30 10:52:47 +0800 CST2015-12-30 10:52:47 +0800 CST 2015-12-30 10:52:47 +0800 CST

Campo de identificador exclusivo com uma condicional

  • 772

Eu tenho um banco de dados que não está em produção, então a tabela principal sendo CustodyDetails, esta tabela tem uma ID int IDENTITY(1,1) PRIMARY KEYcoluna e estou procurando uma maneira de adicionar outro identificador exclusivo que não seja referenciado em nenhuma outra tabela, eu pensaria levando isso em conta o conteúdo da coluna não seria exatamente uma chave de identidade.

Esta nova coluna de identidade tem alguns detalhes específicos, e é aqui que meu problema começa. O formato é o seguinte: XX/YYonde XX é um valor incrementável automaticamente que reinicia/reinicia a cada novo ano e YY são os últimos 2 dígitos do ano atual SELECT RIGHT(YEAR(GETDATE()), 2).

Então, por exemplo, vamos fingir que um registro é adicionado um dia a partir de 28/12/2015 terminando em 03/01/2016 , a coluna ficaria assim:

ID    ID2     DATE_ADDED
1     1/15    2015-12-28
2     2/15    2015-12-29
3     3/15    2015-12-30
4     4/15    2015-12-31
5     1/16    2016-01-01
6     2/16    2016-01-02
7     3/16    2016-01-03

Pensei em usar o frontend para analisar o ID composto (ID2 no exemplo), obter os 2 últimos dígitos e comparar com os 2 últimos dígitos do ano atual e então decidir se inicia ou não um novo correlativo. Claro que seria ótimo poder fazer tudo isso no lado do banco de dados.

EDIT 1: btw, eu também vi pessoas usando tabelas separadas apenas para armazenar chaves de identidade paralelas, então uma chave de identidade de tabela se torna uma chave secundária de segunda tabela, isso soa um pouco duvidoso, mas talvez seja esse o caso de tal implementação?

EDIT 2: Este ID extra é uma referência de documento legado que rotula cada arquivo/registro. Acho que alguém poderia pensar nisso como um alias especial para o ID principal.

O número de registros que este banco de dados lida anualmente não passou dos 100 nos últimos 20 anos e é altamente (realmente, extremamente altamente) improvável que fosse, é claro, se ultrapassar 99, o campo será capaz de continue com o dígito extra e o frontend/procedimento poderá ultrapassar 99, então não é como se isso mudasse as coisas.

É claro que alguns desses detalhes não mencionei no início porque apenas restringiriam as possibilidades de solução para atender à minha necessidade específica, tentei manter o leque de problemas mais amplo.

sql-server sql-server-2005
  • 1 1 respostas
  • 1311 Views

1 respostas

  • Voted
  1. Best Answer
    Hannah Vernon
    2015-12-30T11:15:50+08:002015-12-30T11:15:50+08:00

    Você pode usar uma tabela de chaves para armazenar a parte incrementada de sua segunda coluna de ID. Essa solução não depende de nenhum código do lado do cliente e é automaticamente ciente de vários anos; quando o @DateAddedparâmetro passar em um ano não utilizado anteriormente, ele começará automaticamente a usar um novo conjunto de valores para a ID2coluna, com base naquele ano. Se o proc for consequentemente usado para inserir linhas de anos anteriores, essas linhas serão inseridas com valores "corretos" para o incremento. O GetNextID()proc é voltado para lidar com possíveis impasses normalmente, apenas passando um erro para o chamador se ocorrerem 5 impasses sequenciais ao tentar atualizar a tblIDstabela.

    Crie uma tabela para armazenar uma linha por ano contendo o valor de ID usado atualmente, juntamente com um procedimento armazenado para retornar o novo valor a ser usado:

    CREATE TABLE [dbo].[tblIDs]
    (
        IDName nvarchar(255) NOT NULL,
        LastID int NULL,
        CONSTRAINT [PK_tblIDs] PRIMARY KEY CLUSTERED 
        (
            [IDName] ASC
        ) WITH 
        (
            PAD_INDEX = OFF
            , STATISTICS_NORECOMPUTE = OFF
            , IGNORE_DUP_KEY = OFF
            , ALLOW_ROW_LOCKS = ON
            , ALLOW_PAGE_LOCKS = ON
            , FILLFACTOR = 100
        ) 
    );
    GO
    
    CREATE PROCEDURE [dbo].[GetNextID](
        @IDName nvarchar(255)
    )
    AS
    BEGIN
        /*
            Description:    Increments and returns the LastID value from
                            tblIDs for a given IDName
            Author:         Max Vernon / Mike Defehr
            Date:           2012-07-19
    
        */
        SET NOCOUNT ON;
    
        DECLARE @Retry int;
        DECLARE @EN int, @ES int, @ET int;
        SET @Retry = 5;
        DECLARE @NewID int;
        WHILE @Retry > 0
        BEGIN
            SET @NewID = NULL;
            BEGIN TRY
                UPDATE dbo.tblIDs 
                SET @NewID = LastID = LastID + 1 
                WHERE IDName = @IDName;
    
                IF @NewID IS NULL
                BEGIN
                    SET @NewID = 1;
                    INSERT INTO tblIDs (IDName, LastID) 
                    VALUES (@IDName, @NewID);
                END
                SET @Retry = -2; /* no need to retry since the 
                                      operation completed */
            END TRY
            BEGIN CATCH
                IF (ERROR_NUMBER() = 1205) /* DEADLOCK */
                    SET @Retry = @Retry - 1;
                ELSE
                    BEGIN
                    SET @Retry = -1;
                    SET @EN = ERROR_NUMBER();
                    SET @ES = ERROR_SEVERITY();
                    SET @ET = ERROR_STATE()
                    RAISERROR (@EN,@ES,@ET);
                    END
            END CATCH
        END
        IF @Retry = 0 /* must have deadlock'd 5 times. */
        BEGIN
            SET @EN = 1205;
            SET @ES = 13;
            SET @ET = 1
            RAISERROR (@EN,@ES,@ET);
        END
        ELSE
            SELECT @NewID AS NewID;
    END
    GO
    

    Sua tabela, juntamente com um procedimento para inserir linhas nela:

    CREATE TABLE dbo.Cond
    (
        CondID INT NOT NULL
            CONSTRAINT PK_Cond
            PRIMARY KEY CLUSTERED
            IDENTITY(1,1)
        , CondID2 VARCHAR(30) NOT NULL
        , Date_Added DATE NOT NULL
    );
    
    GO
    CREATE PROCEDURE dbo.InsertCond
    (
        @DateAdded DATE
    )
    AS
    BEGIN
        DECLARE @NextID INT;
        DECLARE @Year INT;
        DECLARE @IDName NVARCHAR(255);
        SET @Year = DATEPART(YEAR, @DateAdded);
        DECLARE @Res TABLE
        (
            NextID INT NOT NULL
        );
        SET @IDName = 'Cond_' + CONVERT(VARCHAR(30), @Year, 0);
        INSERT INTO @Res (NextID)
        EXEC dbo.GetNextID @IDName;
    
        INSERT INTO dbo.Cond (CondID2, Date_Added)
        SELECT CONVERT(VARCHAR(30), NextID) + '/' + 
            SUBSTRING(CONVERT(VARCHAR(30), @Year), 3, 2), @DateAdded
        FROM @Res;
    END
    GO
    

    Insira alguns dados de amostra:

    EXEC dbo.InsertCond @DateAdded = '2015-12-30';
    EXEC dbo.InsertCond @DateAdded = '2015-12-31';
    EXEC dbo.InsertCond @DateAdded = '2016-01-01';
    EXEC dbo.InsertCond @DateAdded = '2016-01-02';
    

    Mostre as duas tabelas:

    SELECT *
    FROM dbo.Cond;
    
    SELECT *
    FROM dbo.tblIDs;
    

    Resultados:

    insira a descrição da imagem aqui

    A tabela de chaves e o procedimento armazenado vêm desta questão.

    • 6

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

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

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

    • 4 respostas
  • Marko Smith

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

    • 10 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
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +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

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