2010-12-18 5 views
2

ich dieses alghorithm ein schreiben und es ist richtig: Tische waren:Wie eine benutzerdefinierte alphanumerischen Primärschlüssel in SQL Server 2005 erstellen

create table PrimKeyTest (primarykeycolumn varchar(8), nextcolumn int) 
GO 
insert into PrimKeyTest values ('P09-0001', 1) 
GO 

und Meine Funktion ist:

set ANSI_NULLS ON 
set QUOTED_IDENTIFIER ON 
GO 
CREATE function [dbo].[GetSpecialPrimaryKey](@yearvalue int) 
returns nvarchar(8) 
as 

begin 

    declare @maxkey varchar(4) 
    declare @maxLength int, @maxkeylength int 

    set @maxLength = 4 

select @maxkey = ISNULL(cast(max(cast(substring(primaryKeycolumn, 5, 4) as integer)+1) as varchar),'1') 
from PrimKeyTest 
     where substring(primaryKeycolumn, 2, 2) = substring(convert(varchar, @yearvalue), 3, 2) 

    set @maxkeylength = len(@maxkey) 

    while @maxkeylength < @maxLength 
    begin 
     set @maxkey = '0' + @maxkey 
     set @maxkeylength = len(@maxkey) 
    end 

    return 'P' + substring(convert(varchar, @yearvalue), 3, 2) + '-' + @maxkey 

end 

Wenn ich jetzt die letzte Zeile dieser Tabelle lösche, gibt der neue letzte Eintrag die richtige Nummer, z. P09-0001 P09-0002 P09-0003 P09-0004 P09-0005 aber wenn ich die zweite Zeile dieser Tabelle lösche, hat die Reihenfolge der primären Spalte inkorrekt z. P09-0001 P09-0003 P09-0004 P09-0005 Können Sie mir helfen? Ich will das: P09-0001 P09-0002 P09-0003 P09-0004

Antwort

3

Dies ist eigentlich kein guter Ansatz im Umgang mit Primärschlüsseln. Dies bedeutet, dass Sie alle Ihre p-Befehle neu ausrichten müssen, wenn eine gelöscht wird (außer wenn es die letzte ist). Dies könnte ein komplexer, kostspieliger und fehleranfälliger Prozess sein. Zum Beispiel haben Sie einen pkey in dieser Tabelle, der wahrscheinlich über einen Fremdschlüssel aus anderen Tabellen referenziert wird. Wenn Sie den Wert des pKey in der ersten Tabelle ändern, müssen Sie ihn auch in allen anderen Tabellen ändern, die darauf verweisen. Das bedeutet, dass alle Einschränkungen für die Dauer der Änderung usw. fallengelassen werden.

Es sieht so aus, als ob Sie versuchen, eine Kennung zu erstellen, die dem Endbenutzer höchstwahrscheinlich präsentiert wird. Sie können weitermachen und Ihre Funktion dazu verwenden, ABER machen Sie es nicht zu einem Primärschlüssel. Verwenden Sie eine automatisch inkrementierende Spalte als Primärschlüssel und den Wert 'P09-N' als separates Feld. Wenn Sie dann die Werte ändern möchten, können Sie dies tun, ohne den Rest Ihres Tabellendesigns zu beeinflussen.

Jetzt, um die Bezeichnerwerte für die Tabelle zu aktualisieren, wann immer eine gelöscht wird, müssen Sie wahrscheinlich einen Cursor in einer gespeicherten Prozedur verwenden. Hier ist eine gute overview on cursors. Sie können auch CTEs (Common Table Expressions) verwenden, um die updating zu tun.

Hier ist ein Beispiel, in dem Cursor Col1 Ihre pTaste und Col2 ist die Kennung Sie ändern möchten:

begin tran -- it's important to wrap this in a transaction! 

declare @counter int 
set @counter = 1 
declare @val varchar(50) 

DECLARE crs CURSOR 
FOR SELECT Col1 FROM TblTest ORDER By Col1 

OPEN crs 
FETCH NEXT FROM crs INTO @val 
WHILE @@FETCH_STATUS = 0 
BEGIN 

    UPDATE TblTest 
    SET Col2 = 'P09-' + cast(@counter as varchar(50)) 
    WHERE Col1 = @val 

    SET @counter = @counter + 1 

    FETCH NEXT FROM crs INTO @val 
END 
CLOSE crs 
DEALLOCATE crs 

commit tran 

ich die führende Null-Logik nicht tun, aber Sie können Google leicht für das ziemlich.

+1

+1 Vielleicht möchte er nicht die Primärschlüssel neu anordnen, sondern nur gelöschte Schlüssel wiederverwenden. Aber das klingt auch nicht nach einer guten Idee. –

+0

Wow, es geht. VIELEN DANK . << Paul Sasik SIE SIND DIE BESTEN >> – hamed

Verwandte Themen