Frage zu der Erstellugn einer Sequenz

Hallo zusammen !

ich habe mal eine Frage. Ich möchte eine Sequenz für meine Postgre SQL Datenbank erstellen. Ich habe die Tabelle test und möchte aus dieser jetzt automatisch den größter ID Wert (einen Int Wert) auslesen und diesen um eins erhöhen. Ich möchte also sicherstellen, dass nie ein bereits vorhandener Wert überschrieben wird. Folgende Create Anweisungn habe ich erstellt:

  CREATE SEQUENCE test
  INCREMENT 1
  MINVALUE SELECT Max(id) + 1 FROM test;
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;

Ist das so bereits korrekt und ausreichend?

Grüße
Kossy

Nein.

Das ist zuviel.

test=# create sequence kossy;
CREATE SEQUENCE
test=*# create table kossy1(id serial, id2 int default nextval('kossy'), val text);
NOTICE:  CREATE TABLE will create implicit sequence "kossy1_id_seq" for serial column "kossy1.id"
CREATE TABLE
test=*# insert into kossy1(val) values ('entweder eine Sequence exliziert erstellen, oder beim create table SERIAL als Datentyp nehmen. Das hochzaehlen passiert von selber');
INSERT 0 1
test=*# select * from kossy1;
 id | id2 |                                                                val

----+-----+--------------------------------------------------------------------------------------------------------------------
----------------
  1 |   1 | entweder eine Sequence exliziert erstellen, oder beim create table SERIAL als Datentyp nehmen. Das hochzaehlen pass
iert von selber
(1 row)

test=*#

Andreas

Hallo !

Nein.

Das ist zuviel.

Ich hoffe nicht, dass du das ironisch meintest!?

Vielleicht noch einmal etwas zu meiner Datenbanktabelle. Dort können aber bereits schon Werte vorhanden sein und durch einen Datenimport wird diese dann vergrößert. Jetzt möchte ich sicherstellen, dass immer der Maximalste Wert aus der Tabelle + 1 gerechnet wird, wenn eine neue Sequenznummer vergeben wird. Wird das mit deinem Vorschlag auch schon abgedeckt??

Ahh, okay. In dem Fall solltest Du PostgreSQL: Documentation: 9.2: Sequence Manipulation Functions lesen und vielleicht dann auch den Default-Wert der Spalte in dieser Tabelle auf nextval() setzen.

Andreas

Hallo !

Danke nochmal für deinen Post.

Vielleicht habe ich mich auch ein wenig missverständlich ausgedrückt. Ich habe eine bestehende Tabelle, die mit Daten gefüllt ist. Dazu existiert auch bereits eine Sequenz.

Nun findet durch irgendeinen Automatismus ein Datenimport statt. Die bestehende Tabelle wurde jetzt mit neuen Daten ergänzt. Und nun möchte ich eigentlich nur die Sequenz aktualisieren, würde hier nicht evtl. auch ein ALTER Sequence mit den entsprechenden Werten passen:

ALTER SEQUENCE testseq
  INCREMENT 1
  MINVALUE SELECT Max(id) + 1 FROM test
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;

Wenn eine solche Alter Anweisung möglich st, wäre es für mich wichtig zu wissen, ob meine vermuteten Werte so passen könnten.

Beste Grüße
Kossy

IIRC will PG da bei ALTER SEQUNCE feste Werte, die ‘on-the-fly’ zu berechnen geht wohl nicht. Du könntest das als dynamischen SQL zusammenbasteln, aber ganz allgemein ist es üblich, für sowas die bereitgestellte Funktion setval() zu nehmen.

Andreas

Hallo nochmal !

Andreas würdest Du dich bereiterklären, mir vieleicht ein kleines ALTER Table Beispiel mit der Funktion setval() zu zeigen? Ich versteh das ehrlich gesagt noch nciht so ganz.

Es ist schade, dass meine on the fly Berechnung nicht funktioniert.

Grüße
Kossy

hoffentlich klein genug:

test=# create table kossy (i int, v text);
CREATE TABLE
test=*# insert into kossy values(23, 'test1');
INSERT 0 1
test=*# create sequence seq_kossy;
CREATE SEQUENCE
test=*# select setval('seq_kossy'::regclass, (select max(i) from kossy));
 setval
--------
     23
(1 row)

test=*# alter table kossy alter column i set default nextval('seq_kossy'::regclass);
ALTER TABLE
test=*# insert into kossy(v) values ('test2');
INSERT 0 1
test=*# select * from kossy ;
 i  |   v
----+-------
 23 | test1
 24 | test2
(2 rows)

Andreas

Hallo Andreas !

Ich habe mir dein Besipiel angesehen und habe dazu noch einmal eine Frage.

Du verwendest eine CREATE SEQUENCE Anweisung, aber ist mein Vorhaben auch mit einer ALTER Sequence möglich und wenn ja, wie genau muss hierfür der Code aussehen?

Ich versteh nciht ganz, warum du in deinem Code test=# schreibst. Ich weiß nicht, ob es für dich noch von Bedeutung ist, aber ich nutze Java als Programmiersprache und kein PHP.

Grüße
Kossy

ALTER geht sicher auch, dazu muß eine Sequence da sein, und Du wirst beim ALTER feste Werte angeben müssen.


Ich versteh nciht ganz, warum du in deinem Code > test=# > schreibst. Ich weiß nicht, ob es für dich noch von Bedeutung ist, aber ich nutze Java als Programmiersprache und kein PHP.

Grüße
Kossy

Das ist Copy&Paste aus psql heraus. test=# ist da lediglich der Prompt.


Andreas

Hallo Andreas,

ich verstehe nicht so ganz, wie ein exaktes Create Statement für eine solche Sequenz aussehen muss, wenn ich mit Methoden wie setval() oder nextval() arbeiten soll. Wäre das so korrekt:

CREATE SEQUENCE test

INCREMENT 1
MINVALUE setval(‘Name meiner Sequenz’, SELECT Max(id) FROM test);
MAXVALUE 9223372036854775807
START 1
CACHE 1;

Brauche ich eigentlich das Startattribut hier zwingend? Muss ich jetzt den Defaultwert des hochzuzählenden Feldes in meiner SQL Tabelle noch anpassen?

Grüße
Kossy

Erstell doch einfach die Sequence (ohne weitere Optionen) und nutze setval() um den Startwert zu setzen. Und wenn die Tabelle ohne SERIAL und ohne Default erstellt wurde und die Sequence nachträglich kommt, ja, dann mußt Du die Tabelle anpassen.

Vielleicht einfach mal die gezeigten Beispiele sinnentnehmend lesen?


Andreas

die Antworten von Andreas sind oft “sehr kurz” … aber “präzise”.

du kannst ja vorab die “höchste ID” abfragen.
wenn du Type “serial” verwendest wird ja “automatisch” eine “Sequence” angelegt mit der Syntax

cTable_Fieldname_seq

eine Query müsste also so aussehen ( Xbase++ Syntax)

cQuery := "SELECT * FROM " + cTable + "_" + cfield + "_seq"

das Ergebniss aus dem Resultset sollte = currval() sein.

p.s. da man mittels NextVal() “hoch zählt” sollte dein “Zähler” ( Aktueller Wert ) immer “aktuell” sein.

frage an Andreas : wenn man nun “viele” Datensätze importieren will, “wie” stellt man sicher das andere Clients nicht “dazwischen pfuschen” ?

Den Wert einer Sequence sollte man nicht für irgend etwas interpretieren. Eine Sequene ist dazu da, einen eindeutigen Wert zu liefern, dieser muß aber nicht zwingend streng mit immer gleicher Schrittweite sein. Von daher stellt sich also Deine Frage nicht.

Andreas

hi,

danke für die Antwort.

wenn ich nun eine grosse DBF importieren will und die in 10 Threads aufteile und jeder Thread per NextVal() auf die selbe “Sequence” zugreift …

gibt es das “Limits” die man beachten sollte ?

Ja, natürlich gibt es Limits zu beachten: die Hardware, die muß das auch schaffen. Sequencen sind thread-safe.

Andreas

klar … aber muss man nicht “irgendwo” die Anzahl für Thread / Connection erhöhen ?

em … äh … noch so eine Newbie Frage : ich öffne die Table über eine Connection.
wenn ich die Thread starte zum importieren arbeitet jeder Thread über die selbe Connection … (funktioniert)

… oder sollte man für jeden Thread eine “eigene” Connection verwenden ?

“das” wollte ich wissen, Danke.

PostgreSQL startet per Connection einen Prozeß, der das, was da rein kommt, ausführt. Das nutzt eine CPU (oder CPU-Kern). Wenn Du von Deinen 256 CPU’s also alle auslasten willst, machst Du entsprechend viele Verbindungen.

Andreas

ok verstanden … pro Connection nur eine CPU ( Kern).
Danke.