Existem duas maneiras de lidar com isso. A primeira é preparar a string com os valores inseridos nela. A segunda é usar parâmetros de consulta para os quais você pode substituir valores separadamente.
Para o primeiro método, você pode usar uma função como snprintf para preparar o comando que você enviará ao servidor. Por exemplo:
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 */
}
Após este buffer conterá a consulta SQL incluindo o valor real da variável id.
Observe a necessidade de verificar o valor de retorno de snprintf para ver se o buffer estourou.
Observe também que quando uma string está sendo colocada no comando, você precisa garantir que a string não contenha aspas ou outros caracteres especiais. Se a string vier de fora do seu programa, por exemplo. A partir da entrada do usuário, a falha em citá-la corretamente deixa um grande buraco através do qual alguém pode injetar algum SQL malicioso. libpq fornece o PQescapeLiteral função para isso.
O outro método, que é preferível na maioria dos casos, é passar o comando SQL e os parâmetros para o servidor separadamente. Por exemplo, você pode fazer isso usando PQexecParams função libpq. Sua string SQL ficaria assim:
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 */
);
Esta função permite fornecer parâmetros e/ou obter resultados em formato texto ou binário. Para simplificar, meu exemplo acima assume o formato de texto para ambos.
Uma variação disso é usar declarações preparadas. Nesse caso, você faz duas chamadas separadas para libpq:
-
Chame PQprepare, para o qual você passa sua instrução SQL com valores de parâmetro $1, $2, etc, conforme meu exemplo acima. Isso retornará um identificador de instrução.
-
Chame PQexecPrepared, para o qual você passa o identificador de instrução e também os próprios parâmetros, especificados de maneira semelhante a PQexecParams.
A vantagem de usar duas etapas como essa é que você pode preparar a instrução uma vez e executá-la várias vezes, o que reduz a quantidade de sobrecarga do servidor associada à análise e ao planejamento da consulta.