594

私はテーブルを持っています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エスケープメカニズムを使用することは可能ですか?

4

7 に答える 7

1022

文字列リテラル

それらを二重にして単一引用符をエスケープ'する ->''は標準的な方法であり、もちろん機能します:

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

`Postgres では (他の特定の RDBMS とは異なり) 特別な目的を持たないバッククォートではなく"、識別子に使用される二重引用符ではなく、単純な単一引用符 (ASCII / UTF-8 コード 39) に注意してください。

古いバージョンで、またはまだ or を使用して実行しているstandard_conforming_strings = off場合、通常、文字列の前に を付けてPosix エスケープ文字列構文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の答えにはそれ以上のものがあります。詳細:

Postgres 内の値

データベース内の値を扱う場合、文字列を適切に引用するための便利な関数がいくつかあります:

  • quote_literal()またはquote_nullable()- 後者NULLは null 入力の文字列を出力します。(有効な SQL識別子quote_ident()を取得するために必要な文字列を二重引用符で囲む必要もあります。)
  • format()フォーマット指定子を使用すると、%Lと同等quote_nullable()です。
    お気に入り:format('%L', string_var)
  • concat()またはconcat_ws()、ネストされた単一引用符とバックスラッシュをエスケープしないため、通常、この目的には適していません。
于 2012-09-07T15:06:16.447 に答える
51

あなたの質問は、アプリケーションにギャップのあるSQL インジェクションホールがある可能性があることを示唆しているため、これは非常に多くの悪い世界です。

パラメータ化されたステートメントを使用する必要があります。Java の場合PreparedStatement、 placeholders とともに使用します。あなたはパラメーター化されたステートメントを使用したくないと言いますが、その理由を説明していません。率直に言って、それらはあなたが試みている問題を修正するための最も簡単で安全な方法であるため、それらを使用しない非常に正当な理由でなければなりません解決する。

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

PgJDBC には、文字列の引用とエスケープのためのパブリック関数はありません。それは、それが良い考えのように見えるかもしれないという理由の一部です。

組み込みの引用関数とPostgreSQL がありますが、それらは を使用する関数用です。最近では、より安全簡単なため、パラメーター化されたバージョンであるによってほとんど廃止されています。これらはサーバー側の機能であるため、ここで説明する目的には使用できません。quote_literalquote_identPL/PgSQLEXECUTEquote_literalEXECUTE ... USING


');DROP SCHEMA public;--悪意のあるユーザーから値を取得するとどうなるか想像してみてください。あなたは以下を生成します:

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

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

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

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

于 2012-09-07T11:36:45.183 に答える
46

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

文字列定数内に単一引用符を含めるには、'Dianne''s horse' のように、2 つの隣接する単一引用符を記述します。

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

于 2012-09-07T11:23:33.580 に答える
31

postgresql で値を挿入したい場合は'、そのために追加の値を指定する必要があります'

 insert into test values (1,'user''s log');
 insert into test values (2,'''my users''');
 insert into test values (3,'customer''s');
于 2012-09-07T20:44:21.213 に答える