Ich weiß Cursor sind schlecht, aber ich denke, ich habe einen Anwendungsfall, wo sie notwendig sind. Ich habe eine Tabelle (tbl_Items) mit einer Spalte (Item_Code), die ein eindeutiger, zufällig generierter alphanumerischer Code (6 Zeichen) sein soll. Ich habe eine Funktion mit einer Schleife, die einen zufälligen Code erzeugt, prüft, ob sie bereits in der Tabelle existiert und den 6-stelligen Code zurückgibt, sobald er einen unbenutzten Code findet.SQL Cursor Loop Einfrieren ohne Fehler
Neue Datensätze in der Tabelle tbl_Items beginnen mit Item_Code, das NULL ist. Ich muss ein UPDATE für alle diese neuen Datensätze ausführen und den Item_Code auf den Rückgabewert der Funktion festlegen. Ich kann natürlich nicht alles mit einer einzigen UPDATE-Anweisung tun, da die Funktion nicht in der Lage ist, den Item_Code jeder neuen Zeile auf Eindeutigkeit zu prüfen, bis die gesamte Transaktion abgeschlossen ist.
Also der CURSOR. Hier ist, was ich gerade habe:
Ich habe die Druckzeile hinzugefügt, nur um zu sehen, was vor sich ging. Ich bekomme ständig 10 erfolgreich aktualisierte Zeilen, dann stoppt es einfach komplett. Kein Fehler oder irgendetwas, es bleibt nur "Executing ...", aber die Tabelle tbl_Items wird nicht mehr aktualisiert, und nichts anderes wird im Nachrichtenfenster ausgegeben.
Kann mir hier jemand in die richtige Richtung zeigen? Es gibt ungefähr 40.000 Datensätze in der ersten Abfrage für den CURSOR. Vielen Dank!
UPDATE: Hier ist die Funktion, die den eindeutigen 5-stelligen Code (5, nicht 6) zurückgibt. „Random_view“ ist eine Ansicht, die nur eine einzige Spalte, die ein Zufallswert zwischen 0 und 1.
CREATE FUNCTION [dbo].[generate_unique_code]
(
@ItemId bigint
)
RETURNS varchar(5)
AS
BEGIN
DECLARE @Length int
DECLARE @CharPool varchar(36)
DECLARE @PoolLength int
DECLARE @LoopCount int
DECLARE @RandomString varchar(5)
DECLARE @RandomInt decimal(18,18)
DECLARE @IsUnique bit
DECLARE @CodeExists bigint = NULL
SET @Length = 6
SET @CharPool = 'abcdefghijklmnopqrstuvwxyz'
SET @PoolLength = Len(@CharPool)
SET @LoopCount = 0
SET @RandomString = ''
SET @IsUnique = 0
WHILE (@IsUnique = 0) BEGIN
-- GENERATE UNIQUE 5 CHARACTER STRING
WHILE (@LoopCount < @Length) BEGIN
SELECT @RandomInt = rnd
FROM random_view
SELECT @RandomString = @RandomString + SUBSTRING(@Charpool, CONVERT(int, @RandomInt * @PoolLength), 1)
SELECT @LoopCount = @LoopCount + 1
END
-- CHECK IF CODE ALREADY EXISTS IN THE DATABASE
SELECT @CodeExists = Item_ID
FROM tbl_Items
WHERE Item_Code = LEFT(@RandomString,5)
-- IF CODE IS NOT ALREADY IN THE DATABASE, BREAK LOOP TO USE IT
IF @CodeExists IS NULL BEGIN
SET @IsUnique = 1
END
END
RETURN LEFT(@RandomString,5)
END
Für welches RDBMS ist das? Bitte fügen Sie ein Tag hinzu, um anzugeben, ob Sie 'mysql',' postgresql', 'sql-server',' oracle' oder 'db2' verwenden - oder etwas ganz anderes. –
Was @marc_s sagte plus 'Neue Datensätze in der tbl_Items-Tabelle beginnen mit Item_Code ist NULL' - bedeutet das, dass die Daten bereits da sind, oder fügen Sie Zeilen mit diesem NULL-Wert ein? – cantSleepNow
Entschuldigung, ich habe gerade das sql-server-Tag hinzugefügt. Und ja, die Datensätze werden mit dem NULL-Wert eingefügt. Ich habe ein SSIS-Paket, das eine wöchentliche BULK INSERT von einer CSV-Datei zu einer Staging-Tabelle, dann ein MERGE in die Produktionstabelle zum Einfügen/Aktualisieren von Datensätzen. – ItJustWerks