ďťż
 
[postgres] update i duplicate key ďťż
 
[postgres] update i duplicate key
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

[postgres] update i duplicate key



Arkadiusz 'nare' Kindziuk - 22-06-2007 00:00
[postgres] update i duplicate key
  Co należy zrobić aby działało z unikalnym indeksem na vo?
Przyszedł mi na myśl tylko trigger który kaskadowo będzie
zmieniał po 1 rekordzie, ale to dosyć brzydkie, itp.

CREATE TABLE tbl(
id INTEGER PRIMARY KEY,
vo INTEGER NOT NULL DEFAULT 0 --UNIQUE
);

CREATE OR REPLACE FUNCTION tbl_ins(INTEGER, INTEGER) RETURNS VOID AS $$
DECLARE
lid ALIAS FOR $1;
lvo ALIAS FOR $2;
cnt integer;
BEGIN
SELECT COUNT(*) INTO cnt FROM tbl WHERE vo=lvo;
IF cnt <> 0 THEN
UPDATE tbl
SET vo = vo + 1
WHERE vo >= lvo
;
END IF;
INSERT INTO tbl(id,vo) VALUES(lid,lvo);
END;
$$ LANGUAGE plpgsql;

SELECT tbl_ins(1,1);
SELECT tbl_ins(3,2);
SELECT tbl_ins(2,2);
SELECT tbl_ins(0,1);
SELECT * FROM tbl ORDER BY id;
id | vo
----+----
0 | 1
1 | 2
2 | 3
3 | 4
(4 rows)

--
Arkadiusz Kindziuk
"Zasady zmieniają się całkowicie.
Szachy, nie warcaby. Go, nie szachy.
Rozumiesz?" (c) Neil Gaiman, "Władca Górskiej Doliny"





=?UTF-8?B?RmlsaXAgUmVtYmlhxYJrb3dza2k=?= - 22-06-2007 00:00

  Arkadiusz 'nare' Kindziuk wrote at 2007-06-21 10:21:
> Co należy zrobić aby działało z unikalnym indeksem na vo?
> Przyszedł mi na myśl tylko trigger który kaskadowo będzie
> zmieniał po 1 rekordzie, ale to dosyć brzydkie, itp.
>
> CREATE TABLE tbl(
> id INTEGER PRIMARY KEY,
> vo INTEGER NOT NULL DEFAULT 0 --UNIQUE
> );
>
> CREATE OR REPLACE FUNCTION tbl_ins(INTEGER, INTEGER) RETURNS VOID AS $$
> DECLARE
> lid ALIAS FOR $1;
> lvo ALIAS FOR $2;
> cnt integer;
> BEGIN
> SELECT COUNT(*) INTO cnt FROM tbl WHERE vo=lvo;
> IF cnt <> 0 THEN
> UPDATE tbl
> SET vo = vo + 1
> WHERE vo >= lvo
> ;
> END IF;
> INSERT INTO tbl(id,vo) VALUES(lid,lvo);
> END;
> $$ LANGUAGE plpgsql;
>
> SELECT tbl_ins(1,1);
> SELECT tbl_ins(3,2);
> SELECT tbl_ins(2,2);
> SELECT tbl_ins(0,1);
> SELECT * FROM tbl ORDER BY id;
> id | vo
> ----+----
> 0 | 1
> 1 | 2
> 2 | 3
> 3 | 4
> (4 rows)
>

przy większych zbiorach takie coś zabije wydajność.

co do samego kodu, można tak...

CREATE OR REPLACE FUNCTION tbl_ins(INTEGER, INTEGER) RETURNS VOID AS $$
DECLARE
lid ALIAS FOR $1;
lvo ALIAS FOR $2;
tmpid integer;
BEGIN
IF EXISTS( SELECT * FROM tbl WHERE vo=lvo) THEN
FOR tmpid IN
SELECT id FROM tbl WHERE vo >= lvo ORDER BY vo DESC
FOR UPDATE
LOOP
UPDATE tbl
SET vo = vo + 1
WHERE id = tmpid;
END LOOP;
END IF;
INSERT INTO tbl(id,vo) VALUES(lid,lvo);
END;
$$ LANGUAGE plpgsql;




Arkadiusz 'nare' Kindziuk - 22-06-2007 00:00

  Dnia Thu, 21 Jun 2007 13:48:57 +0200, Filip Rembiałkowski napisał(a):
>> SELECT tbl_ins(1,1);
>> SELECT tbl_ins(3,2);
>> SELECT tbl_ins(2,2);
>> SELECT tbl_ins(0,1);
>> SELECT * FROM tbl ORDER BY id;
>> id | vo
>> ----+----
>> 0 | 1
>> 1 | 2
>> 2 | 3
>> 3 | 4
>> (4 rows)
>>
>
> przy większych zbiorach takie coś zabije wydajność.
>
Jest o tyle dobrze, że mój realny problem jest w drzewie stopnia <= 30.
vo jest niezależne dla dzieci każdego ojca, więc zawsze będę miał małe
zbiory.

> co do samego kodu, można tak...
>
> [...]
> FOR tmpid IN
> SELECT id FROM tbl WHERE vo >= lvo ORDER BY vo DESC
> FOR UPDATE
> LOOP
> UPDATE tbl
> SET vo = vo + 1
> WHERE id = tmpid;
> END LOOP;
> [...]

:-). Dzięki.
Sam jeszcze wpadłem na analogiczny myk z sequence (są dziury w numeracji,
ale porządek jest zachowany). Siłą rzeczy update też jest sekwencyjny.

--
Arkadiusz Kindziuk
"Zasady zmieniają się całkowicie.
Szachy, nie warcaby. Go, nie szachy.
Rozumiesz?" (c) Neil Gaiman, "Władca Górskiej Doliny"
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • effulla.pev.pl
  • comp
    [PostgreSQL] - jak =?ISO-8859-2?Q?zabezpieczy=E6_interesy_tw?==?ISO-8859-2?Q?=F3rcy_systemu_=3F=3F=3F?= postgresql - int/int postgresql Select count(*) czy raczej Select count(ID) [PostgreSQL] jak =?ISO-8859-2?Q?pobra=E6_warto=B6=E6_zwracan?==?ISO-8859-2?Q?=B1_przez_funkcj=EA=3F?= [postgresql] kilka =?ISO-8859-2?Q?rekord=F3w_subquery_jako_?==?ISO-8859-2?Q?string?= [PostgreSQL] Jak =?ISO-8859-2?Q?po=B3=B1czy=E6_funkcje_z_w?==?ISO-8859-2?Q?idokiem?= Postgres - replikcja master-master Dopasowanie do "najlepszego" dopasowania :) [ PostgreSQL] Problemy z =?ISO-8859-2?Q?instalacj=B1_PostgreSQL_na_syste?==?ISO-8859-2?Q?mach_Windows?= =?ISO-8859-2?Q?[psql]_Polskie_t=B3umaczenie_?= =?ISO-8859-2?Q?licencji_BSD_dla_PostgreSQL=3F?=
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • lunadance.htw.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