PostgreSQL에 작은 따옴표로 텍스트 삽입


432

나는 테이블이있다 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 이스케이프 메커니즘을 사용할 수 있습니까?


1
클라이언트 라이브러리를 빠져 나가는 값을 사용하십시오. 자세한 내용을 보려면 데이터베이스에 어떻게 액세스하고 있는지 말해야합니다.
Richard Huxton

@Richard Huxton 데이터베이스는 java에 의해 액세스됩니다.
MAHI

2
따라서 표준 jdbc 자리 표시자를 사용하십시오. 또는 이것이 최선의 선택이 아닌 이유를 설명하십시오.
Richard Huxton

@ Richard Huxton 나는 그것이 최선의 선택이 아니라고 말하지 않고, SQL에서 탈출 방법이 있는지 검색하고 있습니다.
MAHI

음, 아래 Claudix의 답변 @ 볼 수 있지만, 분명히 값 리터럴은 자신의 유형에 따라 탈출 다른 필요합니다 postgresql.org/docs/current/static/datatype.html
리처드 Huxton

답변:


763

문자열 리터럴

작은 따옴표 '를 두 배로 늘려서 탈출 -> ''표준 방법이며 물론 작동합니다.

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

이전 버전에서 또는 여전히 실행 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는 널 입력을위한 문자열 을 출력합니다 . (또한이 quote_ident()따옴표 유효한 SQL 얻을 필요 문자열 식별자를 .)
  • format()형식 지정자와 함께 %L는과 같습니다 quote_nullable().
    처럼:format('%L', string_var)
  • concat()또는concat_ws() 일반적으로 않는 등 좋지 않습니다 하지 중첩 된 따옴표와 백 슬래시 탈출.

1
또한 일부 PgJDBC 버전에 달러 인용 문제가 있음을 주목할 가치가 있습니다. 특히 달러 인용 문자열 내에서 명령문 종결 자 (;)를 무시하지 못할 수도 있습니다.
Craig Ringer

1
이 관련 답변 에는 JDBC 문제에 대한 세부 정보가 있습니다.
Erwin Brandstetter

1
그리고 절차 언어 등의 경우 삽입시 텍스트 열에서 s'tring을 피하고 싶다면 quote_literal (column_name) 문자열 함수를 사용할 수 있습니다.
alexglue

1
$ token $는 대단합니다. 감사.
신화

@ErwinBrandstetter, re "임의의 수준으로 중첩 될 수 있음": SELECT $outer$OUT$inner$INNER$inner$ER$outer$;2 단계 중첩이 여기서 작동하지 않음을 증명합니다.
filiprem

46

귀하의 질문에 아마도 응용 프로그램에 SQL 주입 구멍 이있을 수 있음을 암시하기 때문에 이것은 매우 나쁜 세계입니다 .

매개 변수화 된 명령문을 사용해야합니다. Java의 경우 PreparedStatement자리 표시 자와 함께 사용하십시오 . 당신은 매개 변수화 된 문장을 사용하고 싶지 않다고 말하지만, 왜 그런지 설명하지 않습니다. 솔직히 말해서, 당신이 시도하는 문제를 해결하는 가장 간단하고 안전한 방법이기 때문에 사용하지 않는 것이 좋습니다. 해결하다.

Java에서 SQL 삽입 방지를 참조하십시오 . 바비가 되지 마십시오 의 다음 피해자가 .

PgJDBC에는 문자열 인용 및 이스케이프에 대한 공용 함수가 없습니다. 그것은 좋은 생각처럼 보일 수 있기 때문에 부분적으로입니다.

있습니다 내장 된 기능을 인용 quote_literalquote_identPostgreSQL을에 있지만위한 PL/PgSQL사용하는 기능 EXECUTE. 요즘은 quote_literal대부분에 의해 대체되는 EXECUTE ... USING매개 변수화 버전 이 있기 때문에, 안전 하고 쉽게 . 서버 측 기능이기 때문에 여기서 설명하는 목적으로 사용할 수 없습니다.


');DROP SCHEMA public;--악의적 인 사용자로부터 가치를 얻으면 어떻게 될지 상상해보십시오 . 당신은 생산할 것입니다 :

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

다음 두 문장으로 나누어지고 주석은 무시됩니다.

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

혹시 데이터베이스가 있습니다.


"in"절 (또는 "또는"의 무리)의 일부로 값 목록이있는 "where"절 ( "insert"라고도 함) 한 가지 예외에 동의하는 경향이 있습니다. 목록의 크기를 세고 "in"절을 사용하여 준비된 명령문에 텍스트를 생성 할 수 있다고 가정하지만 해당 사용 사례에서는 이상합니다.
Roboprog

@Roboprog 일부 클라이언트 드라이버 = ANY(?)에서는 배열 매개 변수를 사용할 수 있습니다 .
Craig Ringer

12
필자는 종종 DDL과 함께 데이터를 부트 스트랩하기 위해 이와 같은 리터럴 삽입을 사용했습니다. 'ýou're it wrong'과 같은 답변보다 질문에 대답하려고합니다.
ThatDataGuy

1
@ThatDataGuy 공정한 의견이지만이 질문에서 OP는 의견을 database is accessed by java직접 추가 하여 문제를 직접 해결합니다. 여기에 오는 사람들이 잠재적 위험을 인식하는 것이 매우 중요합니다. 특히 SQL 주입이 소프트웨어 취약점의 1 위 원인 인 경우에 특히 그렇습니다. 일단 문제를 알게되면 사람들은 부트 스트랩 사용 사례와 같이 중요하지 않은시기에 대해 정보에 근거한 결정을 내릴 수 있습니다.
다 보스

바로 그거죠. 사람들은 또한 코드를 많이 복사하여 붙여 넣습니다. 프로덕션 코드에서 매일 SQL 주입 취약점을 보는 것을 중단하는 날 사람들에게 경고하지 않습니다.
Craig Ringer

26

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 매개 변수 도 참조하십시오 .


답장을 보내 주셔서 감사하지만,이 작업을 수행하기위한 내장 함수가 있으면 수동으로 각 문자를 이스케이프 처리해야합니까?
MAHI September

3
@MAHI 만약 그러한 함수가 있다면, PostgreSQL이 아닌 PgJDBC에있을 것입니다. 이스케이프는 클라이언트 측에서 이루어져야하기 때문입니다. 끔찍한 아이디어 이기 때문에 문서화 된 공개 기능은 없습니다 . 잠재적으로 신뢰할 수없는 이스케이프 처리를 수행 할 필요가 없도록 매개 변수화 된 명령문을 사용해야합니다.
Craig Ringer

13

postgresql '에서 값을 삽입 하려면 추가로 제공해야합니다.'

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

인용 문자열이있는 경우 삼중 따옴표 표시에 대한
찬성

간단한 해결책
이므로


2

Pg 내부에서 작업을 수행해야하는 경우 :

to_json(value)

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


이 질문은 JSON과 어떤 관련이 있습니까?
Erwin Brandstetter

1
@ErwinBrandstetter, 죄송합니다, 꺼져있을 수 있습니다 ..하지만 문자열에서 따옴표를 이스케이프
hatenine

1
그것은 또 다른 문제입니다. 당신은 사용할 수 있습니다 format(), quote_literal()또는 quote_nullable()따옴표를 이스케이프합니다. 참조 : stackoverflow.com/a/25143945/939860
어윈 Brandstetter

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.