Es gibt zwei Möglichkeiten, dies zu handhaben. Die erste besteht darin, die Zeichenfolge mit den darin eingefügten Werten vorzubereiten. Die zweite besteht darin, Abfrageparameter zu verwenden, für die Sie Werte separat ersetzen können.
Für die erste Methode können Sie eine Funktion wie snprintf verwenden um den Befehl vorzubereiten, den Sie an den Server senden. Zum Beispiel:
char buffer[512];
int num=snprintf(buffer, sizeof(buffer),
"SELECT name FROM MYTABLE WHERE id=%d", id);
if (num>sizeof(buffer)) {
/* error: buffer was too small */
}
Danach enthält dieser Puffer die SQL-Abfrage einschließlich des tatsächlichen Werts der Variablen id.
Beachten Sie die Notwendigkeit, den Rückgabewert von snprintf zu überprüfen, um zu sehen, ob der Puffer übergelaufen ist.
Beachten Sie auch, dass Sie beim Einfügen einer Zeichenfolge in den Befehl sicherstellen müssen, dass die Zeichenfolge keine Anführungszeichen oder andere Sonderzeichen enthält. Wenn die Zeichenfolge von außerhalb Ihres Programms kommt, z. Wenn Benutzereingaben nicht richtig zitiert werden, entsteht ein großes Loch, durch das jemand schädliches SQL einschleusen könnte. libpq stellt das PQescapeLiteral Funktion dafür.
Die andere Methode, die in den meisten Fällen vorzuziehen ist, besteht darin, den SQL-Befehl und die Parameter separat an den Server zu übergeben. Sie können dies beispielsweise mit PQexecParams tun libpq-Funktion. Ihr SQL-String würde so aussehen:
PGresult r = PQexecParams(conn, /* Connection to database */
"SELECT name FROM mytable WHERE id=$1",
1, /* Number of parameters */
NULL, /* NULL means server should figure out the parameter types */
params, /* Pointer to array of strings containing parameters */
NULL, /* Not needed unless binary format used */
NULL, /* Not needed unless binary format used */
0 /* Result to come back in text format */
);
Mit dieser Funktion können Sie Parameter bereitstellen und/oder Ergebnisse entweder im Text- oder im Binärformat abrufen. Der Einfachheit halber geht mein obiges Beispiel für beide vom Textformat aus.
Eine Variation davon ist die Verwendung vorbereiteter Anweisungen. In diesem Fall führen Sie zwei separate Aufrufe von libpq durch:
-
Rufen Sie PQprepare auf, an das Sie Ihre SQL-Anweisung mit den Parameterwerten $1, $2 usw. übergeben, wie in meinem obigen Beispiel. Dies gibt ein Statement-Handle zurück.
-
Rufen Sie PQexecPrepared auf, an das Sie das Anweisungshandle und auch die Parameter selbst übergeben, die ähnlich wie bei PQexecParams angegeben werden.
Der Vorteil der Verwendung von zwei Schritten wie diesem besteht darin, dass Sie die Anweisung einmal vorbereiten und viele Male ausführen können, wodurch der mit dem Parsen und Planen der Abfrage verbundene Serveraufwand reduziert wird.