web-dev-qa-db-ja.com

PostgreSQLに一重引用符でテキストを挿入する

テーブルtest(id,name)があります。

user's log'my user'customer'sのような値を挿入する必要があります。

 insert into test values (1,'user's log');
 insert into test values (2,''my users'');
 insert into test values (3,'customer's');

上記のステートメントのいずれかを実行するとエラーが発生します。

これを正しく行う方法がある場合は、共有してください。私はどんな準備されたステートメントも欲しくありません。

SQLエスケープメカニズムを使用することは可能ですか?

319
MAHI

二重引用符で'をエスケープする - > ''は標準的な方法であり、もちろん機能します。

'user's log'     -- incorrect syntax (unbalanced quote)
'user''s log'

古いバージョンで、あるいはまだ standard_conforming_strings = off で実行している場合、または一般的に、Posix escape string syntaxを宣言するためにEを先頭に付ける場合は、バックスラッシュ\でもエスケープできます。

E'user\'s log'

しかし、それは一般的には好ましくありません。
たくさんの一重引用符や複数層のエスケープを処理する必要がある場合は、 ドル引用符で囲まれた文字列 を使用してPostgreSQLで地獄を引用することを避けることができます。

'escape '' with '''''
$$escape ' with ''$$

ドル引用符間の混乱をさらに避けるために、各ペアに一意のトークンを追加します。

$token$escape ' with ''$token$

これは任意の数のレベルでネストできます。

$token2$Inner string: $token1$escape ' with ''$token1$ is nested$token2$

クライアントソフトウェアで$文字が特別な意味を持つ場合は注意してください。あなたはそれをさらに逃がさなければならないかもしれません。これはpsqlやpgAdminのような標準のPostgreSQLクライアントには当てはまりません。

これはplpgsql関数や特別なSQLコマンドを書くのにとても便利です。ただし、ユーザー入力が可能な場合は、アプリケーション内でSQLインジェクションを防ぐために準備済みステートメントまたはその他の方法を使用する必要性を軽減することはできません。 @ Craig's answer にもっと詳しい情報があります。もっと詳しく

596

あなたの質問はおそらくあなたのアプリケーションにギャップがある SQLインジェクション の穴があることを暗示しているので、これは非常に多くの悪い世界です。

あなたはパラメータ化されたステートメントを使用するべきです。 Javaの場合、 PreparedStatementとプレースホルダー を使用します。あなたは、パラメータ化された文を使いたくないと言っていますが、 なぜ を説明していません、そして、率直に言って、それらが最も簡単で安全な方法であるから解決しようとしている問題を解決してください。

JavaでのSQLインジェクションの防止 を参照してください。 ボビー の次の犠牲者にならないでください。

PgJDBCには文字列のクォートとエスケープのためのpublic関数はありません。それはそれがそれが良い考えのように見えるようにするかもしれないという理由から部分的です。

PostgreSQLには組み込み引用関数quote_literalquote_identがありますが、それらはEXECUTEを使用するPL/PgSQL関数用です。最近のquote_literalは、 より安全な および より簡単な であるため、 パラメータ化されたバージョン であるEXECUTE ... USINGに置き換えられています。ここで説明する目的でこれらを使用することはできません。それらはサーバー側の機能だからです。


悪意のあるユーザーから値');DROP SCHEMA public;--を取得した場合にどうなるか想像してください。あなたは作り出すでしょう:

insert into test values (1,'');DROP SCHEMA public;--');

これは2つのステートメントと無視されるコメントに分割されます。

insert into test values (1,'');
DROP SCHEMA public;
--');

おっと、あなたのデータベースがあります。

42
Craig Ringer

PostgreSQLのドキュメントによると(4.1.2.1。文字列定数)

 To include a single-quote character within a string constant, write two 
 adjacent single quotes, e.g. 'Dianne''s horse'.

バックスラッシュでエスケープするかどうかを制御する standard_conforming_strings パラメータも参照してください。

17
Claudix

Postgresqlで'を含む値を挿入したい場合は、追加の'を指定する必要があります。

 insert into test values (1,'user''s log');
 insert into test values (2,'''my users''');
 insert into test values (3,'customer''s');
7
Hunter

postgresql chr(int)関数を使用できます。

insert into test values (2,'|| chr(39)||'my users'||chr(39)||');
5

Pg内で作業を終わらせる必要がある場合

to_json(value)

https://www.postgresql.org/docs/9.3/static/functions-json.html#FUNCTIONS-JSON-TABLE

2
hatenine