Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: MSSQL: Warunkowy update pola

Kolejne problemik:
wykonuję update na jakiejś tabeli, być może na wielu wierszach (zależy to od klauzuli where).
Polecenie generowane jest dynamicznie: zarówno lista <field> = <value> w set, jak i lista warunków w where - tak więc de facto nie wiem a priori, które pola update'uję, i nie wiem też, czy update dotyczy jednego czy wielu wierszy.

I teraz haczyk - potrzebuję zrobić coś takiego:
dla każdego wiersza: jeśli zawartość wskazanego a priori pola zmienia wartość (czyli była na liście set i w dodatku nowa wartość jest inna od dotychczasowej), to do innego pola (też wskazanego a priori) ma się wpisać np. 7.

Nie bardzo widzę tutaj procedurę składowaną z kursorem, choć na pierwszy rzut oka to byłoby najprostsze - bo lista wartości pól jest dynamiczna i może dotyczyć różnych pól.

Da się to zrobić bez triggerów? Czy wogóle jest jakiś patent na sprawdzenie podczas update,u każdego wiersza, czy wskazane pole się zmieniło?
Tomasz Poradowski

Tomasz Poradowski Specjalista od
wytwarzania
oprogramowania

Temat: MSSQL: Warunkowy update pola

Piotr Głudkowski:
I teraz haczyk - potrzebuję zrobić coś takiego:
dla każdego wiersza: jeśli zawartość wskazanego a priori pola zmienia wartość (czyli była na liście set i w dodatku nowa wartość jest inna od dotychczasowej), to do innego pola (też wskazanego a priori) ma się wpisać np. 7.

Skoro wszystko generujesz w locie, to chyba nie problem dodać do listy uaktualnianych pól także tego innego pola i użycie niepodobającego Ci się CASE-WHEN-ELSE-END (gdzieś w innym wątku było :) ?
Np.

UPDATE t SET pole1 = nowa_wartość, inne_pole = CASE WHEN pole1 <> nowa_wartość THEN 7 ELSE inne_pole END WHERE...


Tym sposobem niejako "nadpiszesz" pole "inne_pole" tą samą wartością, czyli nic się nie zmieni. Ale to chyba rozwiązuje Twój problem?
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: MSSQL: Warunkowy update pola

Myślałem o tym, ale - jak to w życiu realnym - tak naprawdę to chodziło o monitorowanie 3 pól i sklejanie z literek (z których każda jest inna i każda oznacza modyfikację jednego z tych trzech pól) ciągu, który byłby wpisywany do danego wiersza. Na CASE wyjdzie z tego potworny moloch :)

Ponieważ taki update może dotyczyć max kilkudziesięciu wierszy (wynika to z założeń aplikacji), czyli wydajnościowo nie jest to krytyczne, ostatecznie zrobiłem to na triggerze z kursorem:


CREATE TRIGGER [dbo].[TRG_myTrigger_AFTER_UPDATE]
ON [dbo].[myTable]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;

DECLARE @priKey AS nvarchar(21);
DECLARE @tmpUpdateFlags AS nvarchar(10), @curUpdateFlags AS nvarchar(10);
DECLARE @newCar AS nvarchar(10), @oldCar AS nvarchar(10);
DECLARE @newStatus AS char(1), @oldStatus AS char(1);
DECLARE @newDeleted AS char(1), @oldDeleted AS char(1);

DECLARE C CURSOR LOCAL FAST_FORWARD
FOR SELECT i.PriKey, d.UpdateFlags,
i.Car, i.Status, i.Deleted,
d.Car, d.Status, d.Deleted
FROM inserted i, deleted d
WHERE i.PriKey = d.PriKey
AND (i.Car <> d.Car OR
i.Status <> d.Status OR
i.Deleted <> d.Deleted);
OPEN C;

FETCH NEXT FROM C
INTO @priKey, @curUpdateFlags,
@newCar, @newStatus, @newDeleted,
@oldCar, @oldStatus, @oldDeleted;

WHILE @@fetch_status = 0
BEGIN
IF @curUpdateFlags IS NULL
SET @curUpdateFlags = '';

SET @tmpUpdateFlags = '';

--- check if Car was updated
IF CHARINDEX('C', @curUpdateFlags) = 0 AND @newCar <> @oldCar
SET @tmpUpdateFlags = @tmpUpdateFlags + 'C';

--- check if Status was updated
IF CHARINDEX('S', @curUpdateFlags) = 0 AND @newStatus <> @oldStatus
SET @tmpUpdateFlags = @tmpUpdateFlags + 'S';

--- check if Deleted was updated
IF CHARINDEX('D', @curUpdateFlags) = 0 AND @newDeleted <> @oldDeleted
SET @tmpUpdateFlags = @tmpUpdateFlags + 'D';

IF @tmpUpdateFlags <> ''
UPDATE [dbo].[Integration_INT_OrdCt_Hdr]
SET UpdateFlags = @curUpdateFlags + @tmpUpdateFlags
WHERE OrdCt_ID = @keyOrdCt_ID
AND OrdCt_GUID = @keyOrdCt_GUID

FETCH NEXT FROM C INTO @priKey, @curUpdateFlags,
@newCar, @newStatus, @newDeleted,
@oldCar, @oldStatus, @oldDeleted;
END

CLOSE C;
DEALLOCATE C;
END
Piotr Głudkowski edytował(a) ten post dnia 29.07.10 o godzinie 18:52

Następna dyskusja:

serwer link mssql-&gt;mysql




Wyślij zaproszenie do