Variable Tabelle als Parameter mit anschließendem select

Hallo auch,

folgendes Problem:
Ich möchte prüfen ob ein Link bereits existiert. Da es aber nicht die Möglichkeit gibt, das mit prepared Statements zu machen (da die Tabelle dynamisch abhängig von dem Link ist) dachte ich ich mach das zumindest in plpgsql damit es etwas performanter wird.

Leider versucht der u.g. Code direkt auf “db” zuzugreifen, und nicht auf die Variable.

-- Function: checkiflinkexists(text, text)

--DROP FUNCTION checkiflinkexists(text, text);

CREATE OR REPLACE FUNCTION checkIfLinkExists(varchar, varchar)
  RETURNS boolean AS
'

DECLARE 
   retVal boolean := false;
   resultSet RECORD;
   link1 Alias FOR $1;
   db Alias FOR $2;
BEGIN
   select into resultSet link from db where link = link1 limit 1;
   if found then 
      retVal := true;
   end if;
   return retVal;

END;
'
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION checkIfLinkExists(varchar, varchar) OWNER TO postgres;

Ich bin Anfänger was plpgsql angeht, bin also für jede Erklärung (oder Link zur Erklärung) dankbar!!

Du kannst die Anfrage dynamisch in einem String zusammenbauen und dann ausführen.
Entsprechende Beispiele findest du auch in der pl/pgSQL Dokumentation.

Versteh’ ich nicht.
Ein Prepared Statement (wir reden über Java PreparedStatements oder?) ist doch auch nur ein String der dynamisch zusammengebaut wird. Warum sollte man da nicht eine andere Tabelle verwenden können?

Es gibt keine PreparedStatements wenn die Tabelle dynamisch ist. Steht so in der Doku und ich habs auch getestet, es geht leider nicht. Leider hat aber auch die plpgsql Loesung nicht zum Erfolg gefuehrt (Performance immer noch katastrophal).

-- Function: checkiflinkexists(text, text)

--DROP FUNCTION checkiflinkexists(text, text);

CREATE OR REPLACE FUNCTION checkIfLinkExists(varchar, varchar)
  RETURNS boolean AS
'
DECLARE 
   retVal boolean := false;
   resultSet RECORD;
BEGIN

EXECUTE ''select link from ''
|| quote_ident($1) 
|| '' where link = '' 
|| quote_literal($2)
|| '' limit 1;''
   INTO resultSet;
  if found then 
      retVal := true;
   end if;
   return retVal;

END;
'
LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION checkIfLinkExists(varchar, varchar) OWNER TO postgres;

ich hoffe Links nach extern sind erlaubt, falls nicht bitte entfernen:
Passing Table Names in PreparedStatement (JDBC forum at JavaRanch)

Natürlich geht das:

String sql = "SELECT * FROM " + tableName + " WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setInt(1, 42);
ResultSet rs = pstmt.executeQuery();

Hier sollte man zwischen Prepared Statements in Java und in der Datenbank unterscheiden - bzw. eigentlich unterscheiden, wer die generiert.

Das was Java generiert, kommt in der Datenbank schon als fertiger String an.

String sql = "SELECT * FROM " + tableName + " WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setInt(1, 42);
ResultSet rs = pstmt.executeQuery();

Inzwischen hab ich einiges geaendert und brauche die Datenbank nur noch sehr wenig, der Teil zb. ist vollstaendig rausgeflogen einfach weils nicht performant genug war.

edit:
Und nein, es gibt keine PreparedStatements die eine dynamische Tabelle verpacken wenn es IM sql dynamisch sein soll. Ich meine hier nichts wie "select * from " + irgendEineTabelle; sondern sowas wie: “select * from ?”; und das geht 100% nicht.

Denn was bringt es mir wenn ich (angenommen ich hab 1000 Tabellen) jedes mal bei jeder Tabelle ein neues PreparedStatement generiere - dann ist mein Heap ganz schnell voll.