ďťż
 
[MSSQL] Jak zabezpieczyc pole przed zmiana ďťż
 
[MSSQL] Jak zabezpieczyc pole przed zmiana
Zobacz wiadomości
 
Cytat
A gdyby tak się wedrzeć na umysłów górę, / Gdyby stanąć na ludzkich myśli piramidzie, / I przebić czołem przesądów chmurę, / I być najwyższą myślą wcieloną. . . Juliusz Słowacki, Kordian
Indeks BCB i MySQL subiekt gt fototapeta
 
  Witamy

[MSSQL] Jak zabezpieczyc pole przed zmiana



Adam - 24-12-2006 00:37
[MSSQL] Jak zabezpieczyc pole przed zmiana
  Witam,
zalozmy ze mam tabele i w tej tabeli kolumne STATUS. Wartosci w kolumnie
status moga sie zmieniac tylko rosnąco. Jak po stronie bazy danych
zrealizowac zabezpieczenie przed zmiana w dół - tak zeby ze statusu na
przykład 5 nie dalo sie zejsc na status 4. Baza to MSSQL.
Moglbym co prawda poslugiwac sie procedurami i to za ich pomoca robic
wrzucanie rekordów oraz update i to w nich (procedurach) zawrzec taka
obsluge ale interesuje mnie rozwiazanie dla zwykłego UPDATE. Triggery? Ale
jak?

select @status_przed = status from tabela
select @status_po = status from insert
if @status_po < @status_przed
begin
co rob? :)
end

Prosze o pomoc

--
Pozdrawiam





Adam - 24-12-2006 00:37

  Dnia Sun, 17 Dec 2006 20:16:10 +0100, Adam napisał(a):

> select @status_przed = status from tabela
> select @status_po = status from insert
> if @status_po < @status_przed
> begin
> co rob? :)
> end

OK, juz wiem. No chyba ze jest lepsze rozwiazanie to z przyjemnoscia
poslucham.

create trigger costam on tabela.baza
for update
as
begin

declare
@st_old int,
@st_new int

select @st_old=status from deleted
select @st_new=status from inserted

if(@st_new<@st_old)
begin
rollback
end

end




Marcin A. Guzowski - 24-12-2006 00:37

  Adam napisał(a):
> OK, juz wiem. No chyba ze jest lepsze rozwiazanie to z przyjemnoscia
> poslucham.
>
> create trigger costam on tabela.baza
> for update
> as
> begin
>
> declare
> @st_old int,
> @st_new int
>
> select @st_old=status from deleted
> select @st_new=status from inserted
>
> if(@st_new<@st_old)
> begin
> rollback
> end
>
> end

Nie jest to dobrze napisany kod triggera. Każdy trigger odpala się raz
dla całej transakcji - musi być więc przystosowany do operacji na
zbiorach (sytuacja update'u kilku rekordów), żadne przypisywanie do
zmiennych i instrukcje warunkowe IF nie wchodzą więc w grę (chyba że
robisz to w kursorze, ale rzeźby nie zakładamy).

--
Pozdrawiam,
Marcin Guzowski
http://guzowski.info




adam - 24-12-2006 00:37

  Marcin A. Guzowski napisał(a):

> Nie jest to dobrze napisany kod triggera. Każdy trigger odpala się raz
> dla całej transakcji - musi być więc przystosowany do operacji na
> zbiorach (sytuacja update'u kilku rekordów), żadne przypisywanie do
> zmiennych i instrukcje warunkowe IF nie wchodzą więc w grę (chyba że
> robisz to w kursorze, ale rzeźby nie zakładamy).

Wtrace sie - jak powinien wygladac taki trigger dla updateu wielu
rekordów i to bez kursora?





Marcin A. Guzowski - 24-12-2006 00:37

  adam napisał(a):
> Marcin A. Guzowski napisał(a):
>
>> Nie jest to dobrze napisany kod triggera. Każdy trigger odpala się raz
>> dla całej transakcji - musi być więc przystosowany do operacji na
>> zbiorach (sytuacja update'u kilku rekordów), żadne przypisywanie do
>> zmiennych i instrukcje warunkowe IF nie wchodzą więc w grę (chyba że
>> robisz to w kursorze, ale rzeźby nie zakładamy).
>
> Wtrace sie - jak powinien wygladac taki trigger dla updateu wielu
> rekordów i to bez kursora?

Podobno przykład wart jest tysiąca słów, więc:

CREATE TABLE tabela
(
wiersz int IDENTITY(1,1) PRIMARY KEY,
poleA int,
poleB int,
status int
)

zadanie jak w pierwszym poście w wątku: zabezpieczyć się przed zmianą
wartości status z większej na mniejszą (czyli jeżeli nastąpi taka
próba - cały update ma być wycofany).

Trigger (typu AFTER) powinien wyglądać tak:

CREATE TRIGGER trig_status ON tabela
FOR UPDATE
AS
BEGIN
IF EXISTS(
SELECT 1 FROM tabela T INNER JOIN deleted D
ON (T.wiersz = D.wiersz
and T.status < D.status)
)
BEGIN
ROLLBACK TRAN
RAISERROR(N'Nieobsługiwana zmiana statusu.',11,1)
END
END

--
Pozdrawiam,
Marcin Guzowski
http://guzowski.info




Krzysztof - 24-12-2006 00:37

 
> Podobno przykład wart jest tysiąca słów, więc:
>
> CREATE TABLE tabela
> (
> wiersz int IDENTITY(1,1) PRIMARY KEY,
> poleA int,
> poleB int,
> status int
> )
>
> zadanie jak w pierwszym poście w wątku: zabezpieczyć się przed zmianą
> wartości status z większej na mniejszą (czyli jeżeli nastąpi taka
> próba - cały update ma być wycofany).
>
> Trigger (typu AFTER) powinien wyglądać tak:
>
> CREATE TRIGGER trig_status ON tabela
> FOR UPDATE
> AS
> BEGIN
> IF EXISTS(
> SELECT 1 FROM tabela T INNER JOIN deleted D
> ON (T.wiersz = D.wiersz
> and T.status < D.status)
> )
> BEGIN
> ROLLBACK TRAN
> RAISERROR(N'Nieobsługiwana zmiana statusu.',11,1)
> END
> END
>
>
Mam pytanie czy jeśli jest to wykonywane w transakcji (tryb inny niz read
uncommited) triger (after) bedzie widzial nowe dane w tabeli "tabela T" czy tez
ze wzgledu na transakcje nie bedzie ich widzial i trzeba czytac nie z "tabela T"
tylko z "inserted"?

Krzysztof

PS. sprawdzilbym to sam ale nie mam teraz sql'a pod reka a mnie to nurtuje.

--
Wysłano z serwisu OnetNiusy: http://niusy.onet.pl




Marcin A. Guzowski - 24-12-2006 00:37

  Krzysztof napisał(a):
>> Podobno przykład wart jest tysiąca słów, więc:
>>
>> CREATE TABLE tabela
>> (
>> wiersz int IDENTITY(1,1) PRIMARY KEY,
>> poleA int,
>> poleB int,
>> status int
>> )
>>
>> zadanie jak w pierwszym poście w wątku: zabezpieczyć się przed zmianą
>> wartości status z większej na mniejszą (czyli jeżeli nastąpi taka
>> próba - cały update ma być wycofany).
>>
>> Trigger (typu AFTER) powinien wyglądać tak:
>>
>> CREATE TRIGGER trig_status ON tabela
>> FOR UPDATE
>> AS
>> BEGIN
>> IF EXISTS(
>> SELECT 1 FROM tabela T INNER JOIN deleted D
>> ON (T.wiersz = D.wiersz
>> and T.status < D.status)
>> )
>> BEGIN
>> ROLLBACK TRAN
>> RAISERROR(N'Nieobsługiwana zmiana statusu.',11,1)
>> END
>> END
>>
>>
> Mam pytanie czy jeśli jest to wykonywane w transakcji (tryb inny niz read
> uncommited) triger (after) bedzie widzial nowe dane w tabeli "tabela T" czy tez
> ze wzgledu na transakcje nie bedzie ich widzial i trzeba czytac nie z "tabela T"
> tylko z "inserted"?

Trigger wywoływany jest na koniec transakcji (stąd AFTER) i będąc jej
częścią widzi wszystkie zmiany w niej dokonane. Widzi więc już
zmodyfikowane rekordy w tabeli T (czyli aktualność tabeli T jest taka
sama jak tabeli inserted). Natomiast aby pobrać dane sprzed momentu
otwarcia transakcji, trzeba czytać tabelę deleted (co z resztą ma
miejsce w przedstawionym przeze mnie przykładzie).

--
Pozdrawiam,
Marcin Guzowski
http://guzowski.info
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • effulla.pev.pl
  • comp
    Zdalny =?ISO-8859-2?Q?dost=EAp_do_MSSQL_bez_zarz=B1dzani?==?ISO-8859-2?Q?a?= [MSSQL] =?ISO-8859-2?Q?zgodno=B6ci_z_licencjami_Microsoft_?==?ISO-8859-2?Q?SQL_Server?= [MSSQL 2k] - jak =?ISO-8859-2?Q?pod=B3=B1czy=E6_serwer_na_?==?ISO-8859-2?Q?porcie_innym_ni=BF_1433=3F?= MSSQL Express czy Oracle Express MSSQL 2005 i uruchamianie procedury o =?ISO-8859-2?Q?okre=B6lone?==?ISO-8859-2?Q?j_godzinie?= [MSSQL] ACCESS - SQL =?ISO-8859-2?Q?B=B3ad_w_konwersji_lic?==?ISO-8859-2?Q?zb?= [MSSQL 2000] =?ISO-8859-2?Q?wywo=B3anie_procesu_z_poziomu_?==?ISO-8859-2?Q?job=27a?= [MSSQL 2K] =?ISO-8859-2?Q?Wp=B3yw_ustawie=F1_regionalnych_?==?ISO-8859-2?Q?serwera_na_zapytania?= Pobierananie danych z innej bazy danych w MSSQL Migracja MSSQL 2005 CTP na 2005 Express
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • melooonka.opx.pl
  • Cytat

    Decede mihi sole - nie zasłaniaj mi słonca.
    Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści
    Hoc fac - tak czyń.
    A tergo - od tyłu; z tyłu.
    I czarne włosy posiwieją. Safona

    Valid HTML 4.01 Transitional

    Free website template provided by freeweblooks.com