Mit einer Funktion in eine Tabelle schreiben

Nun ich denke, daß dies auch kein soo großes Problem ist. Aber irgendwo hakt es.

Also ich habe eine Tabelle mit einer Sequenz (das erste Attribut muss mit einer unique-Nummer versehen werden:

CREATE TABLE auktionen(
	aid SERIAL PRIMARY KEY,
	kid INTEGER NOT NULL,
	name VARCHAR(25) NOT NULL,
	frei CHAR(1) DEFAULT 'Y',
	status CHAR(1) DEFAULT '1', -- 1: In Vorbereitung
	sofort NUMERIC(16,2) DEFAULT 0,
	foto VARCHAR(25),
	beschreibung VARCHAR(150),
	startzeit TIMESTAMP NOT NULL,
	endzeit TIMESTAMP NOT NULL,
	startpreis NUMERIC(16,2) DEFAULT 0,
	preis NUMERIC(16,2) DEFAULT 0,
	katid INTEGER NOT NULL,
	FOREIGN KEY(katid)
	REFERENCES kategorie(katid),
	FOREIGN KEY(kid)
	REFERENCES kunden(kid)
);

Und mit dieser Funktion versuche ich da was einzugeben:

CREATE OR REPLACE FUNCTION neue_auktion ( numeric, text, text, text, text, text, text, numeric ) RETURNS text AS $$
DECLARE
    kunden_id    ALIAS FOR $1;
    name         ALIAS FOR $2;
    beschreibung ALIAS FOR $3;
    startzeit    ALIAS FOR $4;
    endzeit      ALIAS FOR $5;
    startpreis   ALIAS FOR $6;
    preis        ALIAS FOR $7;
    kategorie    ALIAS FOR $8;
    
BEGIN
  
   INSERT INTO auktionen ( kid, name, beschreibung, startzeit, endzeit, startpreis, preis, katid ) VALUES ( kunden_id, name, beschreibung, startzeit, endzeit, startpreis, startpreis, kategorie );

   RETURN 'OK';
END;
$$
LANGUAGE plpgsql;

Aber schon bei der Eingabe der Funktion in psql gibt es “Parser-Fehler”?

test2=# \i neue_auktion
psql:neue_auktion:19: FEHLER: Fehler »Syntaxfehler« bei »$1« at character 31
QUERY: INSERT INTO auktionen ( kid, $1 , $2 , $3 , $4 , $5 , $6 , katid ) VALUES ( $7 , $8 , $9 , $10 , $11 , $12 , $13 , $14 )
CONTEXT: SQL statement in PL/PgSQL function “neue_auktion” near line 13
psql:neue_auktion:19: ZEILE 1: INSERT INTO auktionen ( kid, $1 , $2 , $3 , $4 , $5 , …
psql:neue_auktion:19: ^

Wo liegt das Problem, daran, dass ich nicht alle Felder in der Tabelle fülle? Das erste Attribut ist, wie schon erwähnt über eine Sequenz zu füllen. Da darf ich oder brauch ich keine Nummer einzugeben, sondern es wird automatisch eine fortlaufende Nummer vergeben. Ist hier das Problem?

Gruss Christian

was bedeuten die $$ ich kenn eingentlich ’ bei plpgsql.

edit:
das du nicht alle felder füllst sollte eigentlich kein problem sein.

Crypi

[/quote]

Diese $$-Quotes habe ich unter anderem in der Doku gefundenhttp://www.postgresql.org/docs/8.0/interactive/plpgsql-declarations.html

Das Problem habe ich mittlerweile gelöst. Es lag daran, daß ich die lokalen “Funktions-Variablen” die gleichen Namen gegeben habe wie die Attribute in der zu füllenden Tabelle. Jetzt sieht die Funktion so aus:

CREATE OR REPLACE FUNCTION neue_auktion ( numeric, text, text, text, text, text, text, numeric ) RETURNS text AS $$
DECLARE
    my_kunden_id    ALIAS FOR $1;
    my_name         ALIAS FOR $2;
    my_beschreibung ALIAS FOR $3;
    my_startzeit    ALIAS FOR $4;
    my_endzeit      ALIAS FOR $5;
    my_startpreis   ALIAS FOR $6;
    my_preis        ALIAS FOR $7;
    my_kategorie    ALIAS FOR $8;
    
BEGIN
  
   INSERT INTO auktionen ( kid, name, beschreibung, startzeit, endzeit, startpreis, preis, katid ) VALUES ( my_kunden_id, my_name, my_beschreibung, my_startzeit, my_endzeit, my_startpreis, my_startpreis, my_kategorie );

   RETURN 'OK';
END;
$$
LANGUAGE plpgsql;

Ob sie funktioniert werde ich gleich sehen. Aber sie wird von psql angenommen.

Gruss Christian

Hallo Crypi,

wenn man statt des Zeichens " ’ " andere Zeichen verwendet, hat man weniger Probleme bei der multipizität von Apostrophen (Kapitel 38.2 im deutschen Handbuch).



mfg

fristo

Hallo Christian,

zur Optimierung Deiner Funktion kannst Du auf “RETURN ‘OK’;” verzichten, muss allerdings “RETURNS void” definieren.

Da in Deiner Funktion nur SQL-Funktionen ausgeführt werden, kannst Du statt “LANGUAGE plpgsql;” auch “LANGUAGE sql;” angeben.



mfg

fristo

Hallo Fristo,
na da kommt ja noch mehr. Ausserdem bin ich im Moment noch in der Experimentierphase :wink: Ich möchte Heute Abend vielleicht noch mit PL/Perl versuchen!

Ach ja es gibt noch Probleme mit der Funktion:

test2=# SELECT neue_auktion ( 1, ‘robot’, ‘robot’, ‘1999-01-08 04:05:06’, ‘1999-01-08 04:05:06’, ‘10’, ‘10’, ‘1’);
FEHLER: Spalte »startzeit« hat Typ timestamp without time zone, aber der Ausdruck hat Typ text
HINT: Sie müssen den Ausdruck umschreiben oder eine Typumwandlung vornehmen.
CONTEXT: SQL-Anweisung »INSERT INTO auktionen ( kid, name, beschreibung, startzeit, endzeit, startpreis, preis, katid ) VALUES ( $1 , $2 , $3 , $4 , $5 , $6 , $7 , $8 )«
PL/pgSQL function “neue_auktion” line 13 at SQL statement

Woran liegt es jetzt? Wenn ich die numerischen Werte ohne Quotes eintrage dann meckert er wieder über Synatxfehler. Klar wenn keine Begrenzungen da sind!

Hallo Christian,

ist ja schön für Dich, wenn da noch mehr kommt. Da du, wie Du schreibst, in der Experimentierphase, sprich Lernphase bist, ist das Lesen der Doku mit Sicherheit der beste Weg sich das notwendige Know How anzueignen. Dieses wird Dir auch keiner Abnehmen.

Nachdem Du Perl beherrscht, sollte Dir die Ursache der Fehlermeldung, zumal dort auch von Typumwandlung die Rede ist, etwas aussagen. Im Funktionskopf hast Du für viele Variable mal eben dem Typ TEXT definiert. Woher soll eine Variable vom Typ TIMESTAMP den wissen, dass der Wert in einer Varialbe vom Typ TEXT den Wert und Format vom Type timestamp entspricht?



mfg

fristo

Ach nein, das wäre ja einfach :wink:
Ich habe die Funktion jetzt folgendermaßen umgebaut (eigentlich nur die Argumente verändert):

CREATE OR REPLACE FUNCTION neue_auktion ( numeric, text, text, TIMESTAMP, TIMESTAMP, numeric, numeric, numeric ) RETURNS text AS $$
DECLARE
    my_kunden_id    ALIAS FOR $1;
    my_name         ALIAS FOR $2;
    my_beschreibung ALIAS FOR $3;
    my_startzeit    ALIAS FOR $4;
    my_endzeit      ALIAS FOR $5;
    my_startpreis   ALIAS FOR $6;
    my_preis        ALIAS FOR $7;
    my_kategorie    ALIAS FOR $8;
    
BEGIN
  
   INSERT INTO auktionen ( kid, name, beschreibung, startzeit, endzeit, startpreis, preis, katid ) VALUES ( my_kunden_id, my_name, my_beschreibung, my_startzeit, my_endzeit, my_startpreis, my_startpreis, my_kategorie );

   RETURN 'OK';
END;
$$
LANGUAGE plpgsql;

Also er sollte schon erkennen, daß da Daten vom Typ Timestamp kommen. Oder was habe ich übersehen?

Gruss Chrisian

Hallo Christian,

[quote=“columbus”]Ach nein, das wäre ja einfach ]

Prima, jetzt kann man aus dem Funktionskopf ersehen, welche Typen beim Aufruf erwartet werden. Damit hat sich das Problem von innerhalb der Funktion auf außerhalb der Funktion verlagert.

Mit welchen Typen hast Du die Werte für startzeit und endzeit übergeben? Garantiert haben die Werte die Form ‘1999-01-08 04:05:06’ und ‘1999-01-08 04:05:06’ und sind damit sie vom Typ TEXT. Und Die Funktion mag den Typ TEXT nicht, weil sie für diese Parameter den Typ timestamp benötigt.


Versuchs doch mal mit dieser Anweisung:

SELECT neue_auktion ( 1, 'robot', 'robot', '1999-01-08 04:05:06'::timestamp, '1999-01-08 04:05:06'::timestamp, '10', '10', '1');

Funktioniert garantiert. Stand schon in der Fehlermeldung: “Typumwandlung”. Sooooooooooo einfach geht das!



mfg

fristo

@fristo

Danke für die Info!

Crypi

Ok, das läuft jetzt.
Ich habe die Funktion folgendermaßen aufgerufen:

SELECT neue_auktion ( 1::numeric, ‘robot’::text, ‘robot’::text, ‘1999-01-08 04:05:06’::timestamp, ‘1999-01-08 04:05:06’::timestamp, 10::numeric, 10::numeric, 1::numeric);

Allerdings wusste ich nicht daß man mit Datenbank-Parametern so eine Art “Type-Casting” machen kann. Sonst hätte ich das selbst versucht.

Vielen Dank

Gruss Christian

Hallo Christian,

nochmals ganz kurz. Zahlen erkennt die Datenbank immer als NUMERIC. Ein expilzietes casten ist daher für Zahlen nicht notwendig. Allerdings, wenn Du eine Zahl als Text angibts, z.B. ‘1234’, und sie soll in einen numerischen Feld verarbeitet werden, dann musst Du casten: ‘1234’::numeric!

Allerdings wusste ich nicht daß man mit Datenbank-Parametern so eine Art “Type-Casting” machen kann.

Das ist nicht in bei allen Datenbanken so und hat mit dem Konzept von PostgreSQL zu tun. Dafür kannst man die Fähigkeiten der Datenbank selbst erweitern und seine eigen Datentypen mit eigenen Funktionn definieren. Schau Dir hierzu mal das Kapitel Datentypen in der Doku an. Andere Datenbanken beschränken sich da nur auf die Standdardtypen.



mfg

fristo