Te traemos el resultado a este rompecabezas, o por lo menos eso deseamos. Si tienes inquietudes compártelo en un comentario y sin dudarlo te responderemos
Solución:
Literales de cadena
Escapando comillas simples '
doblándolos -> ''
es la forma estándar y funciona, por supuesto:
'user's log' -- incorrect syntax (unbalanced quote)
'user''s log'
En versiones antiguas o si todavía corres con standard_conforming_strings = off
o, en general, si antepone su string con E
declarar escape de posix string sintaxistambién puedes escapar con la barra invertida :
E'user's log'
La barra invertida se escapa con otra barra invertida. Pero eso generalmente no es preferible.
Si tiene que lidiar con muchas comillas simples o múltiples capas de escape, puede evitar citar el infierno en PostgreSQL con cadenas cotizadas en dólares:
'escape '' with '''''
$$escape ' with ''$$
Para evitar aún más la confusión entre las cotizaciones del dólar, agregue un token único a cada par:
$token$escape ' with ''$token$
Que se puede anidar en cualquier número de niveles:
$token2$Inner string: $token1$escape ' with ''$token1$ is nested$token2$
Presta atención si el $
El carácter debe tener un significado especial en el software de su cliente. Puede que tenga que escapar de ella, además. Este no es el caso con los clientes estándar de PostgreSQL como psql o pgAdmin.
Todo eso es muy útil para escribir funciones plpgsql o comandos SQL ad-hoc. Sin embargo, no puede aliviar la necesidad de usar declaraciones preparadas o algún otro método para protegerse contra la inyección SQL en su aplicación cuando la entrada del usuario es posible. La respuesta de @Craig tiene más sobre eso. Más detalles:
- Inyección de SQL en funciones de Postgres vs consultas preparadas
Valores dentro de Postgres
Cuando se trata de valores dentro de la base de datos, hay un par de funciones útiles para citar cadenas correctamente:
quote_literal()
oquote_nullable()
– este último emite el stringNULL
por null aporte. (También hayquote_ident()
para comillas dobles cadenas donde sea necesario para obtener SQL válido identificadores.)format()
con el especificador de formato%L
es equivalente aquote_nullable()
.
Me gusta:format('%L', string_var)
oconcat()
normalmente no son buenos para este propósito como lo hacen no escape de comillas simples anidadas y barras diagonales inversas.concat_ws()
Esto es tantos mundos de cosas malas, porque su pregunta implica que probablemente tenga agujeros de inyección de SQL en su aplicación.
Debería estar usando declaraciones parametrizadas. Para Java, utilice PreparedStatement
con marcadores de posición. Dices que no quieres usar declaraciones parametrizadas, pero no explicas por quéy, francamente, tiene que ser una muy buena razón para no usarlos porque son la forma más sencilla y segura de solucionar el problema que está tratando de resolver.
Consulte Prevención de la inyección de SQL en Java. No seas la próxima víctima de Bobby.
No hay una función pública en PgJDBC para string citando y escapando. Eso es en parte porque podría hacer que parezca una buena idea.
Allá son funciones de cotización incorporadas quote_literal
y quote_ident
en PostgreSQL, pero son para PL/PgSQL
funciones que utilizan EXECUTE
. Estos días quote_literal
está obsoleto en su mayoría por EXECUTE ... USING
Cuál es el versión parametrizadaporque es más seguro y más fácil. No puede usarlos para el propósito que explica aquí, porque son funciones del lado del servidor.
Imagina lo que sucede si obtienes el valor ');DROP SCHEMA public;--
de un usuario malicioso. Producirías:
insert into test values (1,'');DROP SCHEMA public;--');
que se divide en dos declaraciones y un comentario que se ignora:
insert into test values (1,'');
DROP SCHEMA public;
--');
Ups, ahí va tu base de datos.
De acuerdo con la documentación de PostgreSQL (4.1.2.1. Constantes de cadena):
To include a single-quote character within a string constant, write two
adjacent single quotes, e.g. 'Dianne''s horse'.
Consulte también el parámetro standard_conforming_strings, que controla si funciona el escape con barras invertidas.