2017-03-03 2 views
1

Ich muss die Spalte "Order" einer Tabelle aktualisieren, bevor ich eine eindeutige Integritätsregel hinzufüge, um Fehler beim Hinzufügen der Integritätsbedingung zu vermeiden. dieses Feld zu aktualisieren Ich versuche, den folgenden T-SQL-Code tun:Aktualisiere Daten in einer Cursorzeile noch nicht abgerufen sql server

DECLARE c_x CURSOR FOR 
SELECT ID, ISOLD, ISNEW, GROUPID, ORDER, ISENABLED 
FROM mytable 

OPEN c_x; 
FETCH NEXT FROM c_x INTO @ID, @ISOLD, @ISNEW, @GROUPID, @ORDER, @ISENABLED; 

WHILE @@FETCH_STATUS = 0 
BEGIN 
SELECT @SUMOFROWS = COUNT(*) FROM mytable 
    WHERE ISOLD = @ISOLD 
     AND ISNEW = @ISNEW 
     AND GROUPID = @GROUPID 
     AND ORDER = @ORDER 
     AND ISENABLED = @ISENABLED; 


IF @SUMOFROWS > 1 
     BEGIN 
      UPDATE mytable 
      SET ORDER = ORDER+ 1 
      WHERE ISOLD = @ISOLD 
      AND ISNEW = @ISNEW 
      AND GROUPID = @GROUPID 
      AND ISENABLED = @ISENABLED 
      AND ORDER >= @ORDER 
      AND ID <> @ID 

     END 

    FETCH NEXT FROM CURSOR_TIPOS_AGENDA INTO @ID, @ISOLD, @ISNEW, @GROUPID, @ORDER, @ISENABLED 
END 

Tabellendaten:

ID ISOLD ISNEW GROUPID ORDER ISENABLED 
1 1  0  500  1  1 
2 0  0  500  1  1 
3 0  0  500  1  1 

DER NEUE UNIQUE CONSTRAINT

CREATE UNIQUE NONCLUSTERED INDEX [XAK1_mytable] ON mytable([ORDER], [ISENABLED], [ISOLD`], [ISNEW], [GROUPID]) 

die Fehler auf die UNIQUE ADD KONSTRIEREN SIE SICH IN DER TABELLENREIHE MIT ID 3. DER CODE OBEN SOLLTE DIE REIHE MIT ID 3 MIT DER BESTELLUNG AKTUALISIEREN 2

Dieser Code aktualisiert jedoch auch die Zeilen der Tabelle nicht. Jemand weiß, wie kann ich die Zeilen aktualisieren, die ich noch nicht im Cursor abgerufen habe?

+0

Das klingt wie ein [XY Problem] (http://meta.stackexchange.com/a/66378/346416) Können Sie das Problem, das Sie zu lösen versuchen, anstelle des Problems mit Ihrer Lösungsversuch teilen? – SqlZim

Antwort

2

Es sieht so aus, als ob Sie versuchen, Order einzigartig für jeden Satz von GroupId, [Order], IsOld, IsNew, IsEnabled zu machen.

Sie können dies mit einem Satz auf Basis Anweisung ein common table expression mit row_number()

;with cte as (
    select 
     Id 
    , IsOld 
    , IsNew 
    , GroupId 
    , [Order] 
    , IsEnabled 
    , rn = row_number() over (
     partition by GroupId, [Order], IsOld, IsNew, IsEnabled 
     order by [Order] 
     ) - 1 
    from t 
) 
--Preview: 
--/* 
select *, NewOrder = [Order] + rn 
from cte 
where rn > 0 
--*/ 
/* 
--Update 
update cte 
    set [Order] = [Order] + rn 
where rn > 0; 
--*/ 

Sie können mit dem cte wie so überspringen:

update cte 
    set [Order] = [Order] + rn 
from (
    select * 
    , rn = row_number() over (
     partition by GroupId, [Order], IsOld, IsNew, IsEnabled 
     order by [Order] 
     ) - 1 
    from t 
) as cte 
where rn > 0 

Für das oben angegebene Beispiel , Die Auswahlcode zurückkehren würde:

+----+-------+-------+---------+-------+-----------+----+----------+ 
| Id | IsOld | IsNew | GroupId | Order | IsEnabled | rn | NewOrder | 
+----+-------+-------+---------+-------+-----------+----+----------+ 
| 3 |  0 |  0 |  500 |  1 |   1 | 1 |  2 | 
+----+-------+-------+---------+-------+-----------+----+----------+ 

und nach dem Update ausgeführt wird, würde die Tabelle wie folgt aussehen:

+----+-------+-------+---------+-------+-----------+ 
| Id | IsOld | IsNew | GroupId | Order | IsEnabled | 
+----+-------+-------+---------+-------+-----------+ 
| 1 |  1 |  0 |  500 |  1 |   1 | 
| 2 |  0 |  0 |  500 |  1 |   1 | 
| 3 |  0 |  0 |  500 |  2 |   1 | 
+----+-------+-------+---------+-------+-----------+ 

Testaufbau: http://rextester.com/XJAUJ47591

Verwandte Themen