PDO를 사용하여 NULL 값을 어떻게 삽입합니까?


105

이 코드를 사용하고 있으며 좌절감이 없습니다.

try {
    $dbh = new PDO('mysql:dbname=' . DB . ';host=' . HOST, USER, PASS);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
}
catch(PDOException $e)
{
    ...
}
$stmt = $dbh->prepare('INSERT INTO table(v1, v2, ...) VALUES(:v1, :v2, ...)');
$stmt->bindParam(':v1', PDO::PARAM_NULL); // --> Here's the problem

PDO::PARAM_NULL, null, '', 모두 실패하고 다음 오류가 발생합니다.

치명적인 오류 : / opt / ...에서 참조로 매개 변수 2를 전달할 수 없습니다.

답변:


138

난 그냥 PDO를 배우고,하지만 난 당신이 사용할 필요가 있다고 생각 bindValue하지bindParam

bindParam참조 할 변수를 취하고을 호출 할 때 값을 가져 오지 않습니다 bindParam. 나는 이것을 PHP 문서에 대한 주석에서 발견했습니다.

bindValue(':param', null, PDO::PARAM_INT);

편집 : 추신 : 당신은 이것을 bindValue(':param', null, PDO::PARAM_NULL);하고 싶을 수도 있지만 모든 사람에게 효과가 없었습니다 (보고 해 주신 Will Shaver에게 감사드립니다.)


이 둘의 차이점은 잘 모르겠지만 몇 가지를 조사하겠습니다. 감사합니다. 귀하의 답변도 훌륭했습니다.
Nacho

3
나는 이것이 내 것보다 더 나은 대답이라고 생각한다 (실제로 작동한다면)
Joe Phillips

2
MySql 5.1.53에서 PDO :: PARAM_NULL에 문제가 있었지만 Null 값을 가진 PDO :: PARAM_INT는 훌륭하게 작동했습니다.
Will Shaver 2011

2
Odin : 가장 중요한 부분은 세 가지 매개 변수를 모두 전달하는 것입니다. :). IGN의 질문에 그는 대신의 유형으로, 값으로 PDO :: PARAM_NULL를 통과했다 (그리고 전혀 유형을 통과하지.)
JasonWoof

1
참고 : 대부분의 경우 bindValue()over 를 사용 하는 것이 좋습니다 bindParam(). NULL가치 뿐만 아니라 모든 것을 위해 . 매개 변수를 PHP 변수의 참조에 바인딩해야하는 한 가지 경우를 생각할 수 없지만 그게 바로 그 일 bindParam()입니다.
low_rents

48

사용할 때 bindParam()상수가 아닌 변수를 전달해야합니다. 따라서 해당 줄 전에 변수를 만들고 다음으로 설정해야합니다.null

$myNull = null;
$stmt->bindParam(':v1', $myNull, PDO::PARAM_NULL);

시도한 경우 동일한 오류 메시지가 표시됩니다.

$stmt->bindParam(':v1', 5, PDO::PARAM_NULL);

당신이 맞았어요. 방금 전에 제 코드에서 해봤다는 걸 깨달았습니다. $ null = PDO :: PARAM_NULL; 감사.
Nacho

1
어쨌든 자리 표시자를 만들려면이 경우 bindValue ()를 사용하는 것이 좋습니다. bindParam ()은 원래 쿼리를 실행 한 다음 매개 변수를 다시 바인딩하지 않고 변수를 변경하고 다시 실행하기위한 것입니다. bindValue ()는 즉시 바인딩되며 bindParam ()은 실행시에만 바인딩됩니다.
Hugo Zink

1
$ myNull = null 줄에서 null은 소문자 여야합니다. $ myNull = NULL이 작동하지 않았습니다.
raphael75 nov.

28

MySQL에서 INTEGER열 (일 수 있음 NULL) 을 사용할 때 PDO는 예상치 못한 동작을합니다.

를 사용 $stmt->execute(Array)하는 경우 리터럴을 지정해야하며 변수 참조로 NULL제공 할 수 없습니다 NULL. 따라서 이것은 작동하지 않습니다.

// $val is sometimes null, but sometimes an integer
$stmt->execute(array(
    ':param' => $val
));
// will cause the error 'incorrect integer value' when $val == null

그러나 이것은 작동합니다.

// $val again is sometimes null, but sometimes an integer
$stmt->execute(array(
    ':param' => isset($val) ? $val : null
));
// no errors, inserts NULL when $val == null, inserts the integer otherwise

PHP 5.4.1을 사용하여 MySQL 5.5.15에서 이것을 시도했습니다.


1
$ stmt-> execute (array ( ': param'=>! empty ($ val)? $ val : null)); 사용 빈 문자열을 위해 당신은 또한 데이터베이스에 설정된 null로 할 것이기 때문에 비울!
자드 Nizamani

1
@ShehzadNizamani 그의 예에서와 같이 열 유형이 정수인 경우에만 yes입니다. 그러나 그렇지 않으면 isset()더 나은 상관 관계 NULL. 빈 문자열도 값입니다.
StanE 2017

8

여전히 문제가있는 경우 (참조로 매개 변수 2를 전달할 수 없음) PDO에 null을 전달하는 것이 아니라 null 값으로 변수를 정의하십시오.

bindValue(':param', $n = null, PDO::PARAM_INT);

도움이 되었기를 바랍니다.


6

나는 같은 문제가 있었고 bindParam과 함께 작동하는이 솔루션을 발견했습니다.

    bindParam(':param', $myvar = NULL, PDO::PARAM_INT);

3

삽입 할 경우 NULL(가)에만 value있다 empty거나 '',하지만 삽입 value이 가능한 경우.

A) POST 메서드를 사용하여 양식 데이터를 수신하고 해당 값으로 함수 삽입을 호출합니다.

insert( $_POST['productId'], // Will be set to NULL if empty    
        $_POST['productName'] ); // Will be to NULL if empty                                

B) 사용자가 필드를 채우지 않았는지 평가 NULL하고 그럴 경우 삽입 합니다.

public function insert( $productId, $productName )
{ 
    $sql = "INSERT INTO products (  productId, productName ) 
                VALUES ( :productId, :productName )";

    //IMPORTANT: Repace $db with your PDO instance
    $query = $db->prepare($sql); 

    //Works with INT, FLOAT, ETC.
    $query->bindValue(':productId',  !empty($productId)   ? $productId   : NULL, PDO::PARAM_INT); 

    //Works with strings.
    $query->bindValue(':productName',!empty($productName) ? $productName : NULL, PDO::PARAM_STR);   

    $query->execute();      
}

사용자가에 입력하지 아무것도 않는 경우 예를 들어, productName양식의 필드를, 다음 $productName될 것입니다 SET하지만 EMPTY. 따라서인지 확인 empty()하고이면을 삽입해야 NULL합니다.

PHP 5.5.17에서 테스트 됨

행운을 빕니다,


3
또는 IFNULL()쿼리 문자열에서 MySQL의 기능을 사용할 수 있습니다 . : 이것처럼$sql = "INSERT INTO products ( productId, productName ), VALUES ( IFNULL(:productId, NULL), IFNULL(:productName, NULL) )";
starleaf1

나는 당신의 해결책을 청결하게 좋아합니다. 방금 테스트했지만 불행히도 사용자가 입력에 아무것도 쓰지 않으면 NULL 대신 빈 문자열을 삽입합니다. 그것은 단지 선호도의 문제이지만, 빈 문자열 대신 NULL이 있습니다.
Arian Acosta 2014

0

이 시도.

$stmt->bindValue(':v1', null, PDO::PARAM_NULL); // --> insert null

1
이러한 오래된 질문에 답하기 전에 먼저 다른 답을 읽어야합니다. 이미 답변되었을 수 있습니다.
당신의 상식

0

다른 답변을 기반으로하지만이 솔루션을 실제로 사용하는 방법에 대해 좀 더 명확하게 설명합니다.

예를 들어 시간 값에 대한 빈 문자열이 있지만이를 null로 저장하려는 경우 :

  if($endtime == ""){
    $db->bind(":endtime",$endtime=NULL,PDO::PARAM_STR);
  }else{
    $db->bind("endtime",$endtime);
  }

시간 값의 경우 시간이 문자열로 저장되므로 PARAM_STR을 사용합니다.


-1

제 경우에는 다음을 사용하고 있습니다.

  • SQLite,

  • 알 수없는 수의 필드를 처리하기 위해 자리 표시자가있는 준비된 문,

  • 모든 것이 문자열이고 NULL값과 같은 것이없는 사용자가 보낸 AJAX 요청

  • 외래 키 제약 (허용 가능한 값)을 NULL위반하지 않기 때문에 s 를 삽입해야합니다 .

이제 사용자가 post : $_POST[field1]value1으로 빈 문자열 ""또는 "null"또는"NULL" .

먼저 다음과 같이 진술합니다.

$stmt = $this->dbh->prepare("INSERT INTO $table ({$sColumns}) VALUES ({$sValues})");

여기서 {$sColumns}같은 STH이다 field1, field2, ...하고 {$sValues}내 자리 표시 자입니다?, ?, ... .

그 후, 나는 나의 수집 $_POST배열의 열 이름과 관련 데이터 $values 교체 NULL의 :

  for($i = 0; $i < \count($values); $i++)
     if((\strtolower($values[$i]) == 'null') || ($values[$i] == ''))
        $values[$i] = null;

이제 다음을 실행할 수 있습니다.

$stmt->execute($values);

외래 키 제한을 우회합니다.

반면에 빈 문자열이 더 의미가있는 경우 해당 필드가 외래 키의 일부인지 여부를 확인해야합니다 (더 복잡함).

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