문제

PHP에서 MySQL 작업을 수행하기위한 표준 mysql_connect (), mysql_query () 등을 사용했습니다. 최근에 나는 훌륭한 MDB2 클래스를 사용하여 전환했습니다. 그것과 함께 준비된 진술을 사용하고 있으므로 입력 및 SQL 주입 공격을 피하는 것에 대해 걱정할 필요가 없습니다.

그러나 제가 실행하는 문제가 하나 있습니다. varchar 열이 몇 개있는 테이블이 있습니다. 이전 MySQL PHP 명령을 사용하여 아무런 문제없이 이와 같은 일을 할 수 있습니다.

INSERT INTO mytable SET somevarchar = '';

그러나 이제 다음과 같은 쿼리가 있으면 다음과 같습니다.

INSERT INTO mytable SET somevarchar = ?;

그리고 PHP에서 나는 다음과 같습니다.

$value = "";
$prepared = $db->prepare($query, array('text'));
$result = $prepared->execute($value);

이것은 오류가 발생합니다. "null value violates not-null constraint"

임시 해결 방법으로 확인하는지 확인합니다 $value 비어 있고 변경하십시오 " " (단일 공간), 그러나 그것은 끔찍한 해킹이며 다른 문제를 일으킬 수 있습니다.

대신 널을 삽입하려고하지 않고 준비된 진술과 함께 빈 줄을 어떻게 삽입해야합니까?

편집하다: 내 전체 코드베이스를 통과하고 빈 문자열을 사용하는 모든 곳을 찾아서 NULL을 사용하도록 변경하기에는 너무 큰 프로젝트가 너무 큽니다. 내가 알아야 할 것은 표준 MySQL 쿼리가 왜 ""와 null이 두 가지 별도의 것 (정확하다고 생각하는 것처럼)으로 취급하지만 준비된 진술은 "" "" "" "" "" "" "" "두 개의 별도의 것들로 취급되는 이유"입니다.

""와 null은 다음과 같습니다 ~ 아니다 똑같은 것. 예를 들어, SELECT NULL = ""; 보고 NULL 대신에 1 예상대로.

도움이 되었습니까?

해결책

이것은 MDB2 API FUMBING PHP의 오리 타이핑 시맨틱의 문제처럼 들립니다. PHP의 빈 문자열은 NULL과 동일하기 때문에 MDB2는 아마도이를 잘못 치료할 것입니다. 이상적인 솔루션은 API 내에서 해결 방법을 찾는 것이지만 지나치게 익숙하지는 않습니다.

그러나 고려해야 할 한 가지는 SQL의 빈 문자열이 널 값이 아니라는 것입니다. 'NOT NULL'으로 선언 한 행에 삽입 할 수 있습니다.

mysql> CREATE TABLE tbl( row CHAR(128) NOT NULL );
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO tbl VALUES( 'not empty' ), ( '' );
Query OK, 2 rows affected (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT row, row IS NULL FROM tbl;
+-----------+-------------+
| row       | row IS NULL |
+-----------+-------------+
| not empty |           0 | 
|           |           0 | 
+-----------+-------------+
2 rows in set (0.00 sec)

mysql> INSERT INTO tbl VALUES( NULL );
ERROR 1048 (23000): Column 'row' cannot be null

MDB2 API에서 해결 방법을 찾거나 구현할 수없는 경우, 하나의 해킹 솔루션 (현재 사용중인 것보다 약간 낫습니다)은 사용자 변수 빈 문자열의 경우 -

SET @EMPTY_STRING = "";
UPDATE tbl SET row=@EMPTY_STRING;

마지막으로, 삽입 문에서 빈 문자열을 사용해야하지만 자신을 찾을 수없는 경우 MySQL의 문자열 유형의 기본값은 빈 문자열입니다. 따라서 삽입 문에서 열을 생략 할 수 있으며 빈 문자열로 자동으로 설정됩니다 (열에 Null 구속 조건이없는 경우).

다른 팁

일부 답변 덕분에 나는 문제가 MDB2 API에있을 수 있으며 PHP 또는 MySQL 명령 자체가 아니라는 것을 깨달았습니다. 물론, 나는 이것을 MDB2 FAQ에서 발견했다 :

  • 빈 문자열이 데이터베이스에서 널로 끝나는 이유는 무엇입니까? 기본값이 ""인 경우 널 텍스트 필드에서 허용되지 않는 이유는 무엇입니까?
    • 문제는 일부 rdbms (가장 주목할만한 Oracle)의 경우 빈 문자열이 널이라는 것입니다. 따라서 MDB2는 모든 RDBM에서 동일한 동작을 시행하는 휴대 성 옵션을 제공합니다.
    • 모든 휴대 성 옵션이 기본적으로 활성화 되므로이 동작을 원하지 않는 경우 기능을 비활성화해야합니다. $ MDB2-> SETOPTION ( 'portability', MDB2_Portability_all ^ MDB2_Portability_Empty_to_null);

사려 깊은 답변을 제공 한 모든 분들께 감사드립니다.

나는이 질문이 거의 대답하고 은퇴했다는 것을 알고 있지만, 비슷한 상황에 대한 답을 찾는 동안 그것을 발견했으며 반지에 모자를 던지는 것을 거부 할 수는 없습니다.

NULL/""열이 무엇인지 모르면 빈 문자열의 진정한 중요성을 알 수 없습니다. 빈 문자열이 그 자체로 무언가를 의미합니까 (예 : 판사가 내 이름을 단순히 아무것도 바꾸지 말라고 확신했다면, 내 이름이 내 운전 면허증에 널처럼 나타나면 정말 자극을받을 것입니다. 내 이름이 될 것입니다!

그러나 빈 끈 (또는 빈 또는 아무것도없는 것이 아니라 단순히 어떤 것도 부족한 것이 아니라)는 단순히 단순히 "null이 아님"또는 "아무것도 없지만 여전히 널"을 의미 할 수 있습니다. 당신은 다른 방향으로 가서 값의 부재가 없으면 널보다 훨씬 적게 만들어 낼 수 있습니다. 적어도 null은 당신이 큰 소리로 말할 수있는 이름을 가지고 있습니다!

내 요점은 빈 문자열이 일부 데이터를 직접 표현하는 경우 (이름과 같은 또는 내가 선호하는 것이 내 전화 번호의 숫자 사이에 삽입되는 것)라면 옵션이 아프일 때까지 논쟁해야한다는 것입니다. 빈 문자열을 합법적으로 사용하거나 널 있지 않은 빈 문자열을 나타내는 것을 사용하기 위해 (ASCII 제어 문자 또는 일부 유니 코드 등가, 어떤 종류의 regex 값, 또는 심지어는 임의적이지만 완전히 사용되지 않은 토큰을 사용합니다. , 좋아요 : ◘

빈 셀이 실제로 널이 아니라는 것을 의미한다면, 당신은 그것을 표현하는 다른 방법을 생각할 수 있습니다. 어리 석고 명백한 방법 중 하나는 "NOT NULL"이라는 문구입니다. 그러나 나는 null이 "이 그룹의 일부가 아닌 것"과 같은 것을 의미한다는 직감이 있지만 빈 줄은 "이 사람은 멋지다, 그는 아직 갱 문신을 얻지 못했다"는 것을 의미합니다. 어떤 경우에는 "기본값"또는 "신인"또는 "보류"와 같은이 상황에 대한 용어/이름/아이디어가 나옵니다.

이제 미친 기회에 의해 실제로 빈 끈이 널에 합당하지 않은 것을 나타내기를 원한다면, 다시 "-1"또는 "Supernull"또는 "Uglies"와 같은 더 중요한 상징을 생각해냅니다.

인도 카스트 제도에서 가장 낮은 카스트는 Shudra : 농민과 노동자입니다. 이 카스트 아래에는 Dalit이 있습니다 : "손길이 닿지 않습니다". 그들은 카스트로 간주되지 않습니다. 왜냐하면 가장 낮은 카스트로 설정하는 것은 전체 시스템의 오염으로 간주되기 때문입니다.

그러니 빈 줄이 null보다 나빠질 수 있다고 생각하는 것에 대해 나를 미친 짓이라고 부르지 마십시오!

'다음 번까지.

나는 해결책을 찾았다!

mdb2는 mdb2_portability_empty_to_null이 기본적으로 켜져 있기 때문에 빈 문자열을 null로 변환합니다 (빈 줄을 null로 간주하는 Oracle 덕분).

데이터베이스에 연결할 때이 옵션을 끕니다.

$options = array(
    'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL
);
$res= & MDB2::connect("mysql://user:password@server/dbase", $options);

0과 빈 문자열은 변수이지만 null은 데이터가없는 것입니다. 그리고 저를 믿으십시오. 쿼리를 작성하는 것이 훨씬 쉽습니다.

SELECT * from table where mything IS NULL 빈 줄에 대한 쿼리를 시도하는 것보다 :/

빈 따옴표 세트가 아니며 "" 그렇게?

나는 혼란 스럽다. MySQLI OO (태그와 스타일에서)를 사용하는 것처럼 보이지만 구문은 수동 php.net에서 대신 이것을 수행한다고 말합니다.

$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top