PHP에서 MySQL 정수 필드가 문자열로 반환됩니다


127

MySQL 데이터베이스에 테이블 필드가 있습니다.

userid INT(11)

따라서이 쿼리를 사용하여 내 페이지로 호출합니다.

"SELECT userid FROM DB WHERE name='john'"

그런 다음 결과를 처리하기 위해 다음을 수행하십시오.

$row=$result->fetch_assoc();

$id=$row['userid'];

이제 내가하면 :

echo gettype($id);

나는 문자열을 얻는다. 정수가 아니어야합니까?


2
MySQL 쿼리는 행 유형이나 다른 관련 정보가 아닌 행 값을 제공합니다. 각 테이블 셀에있는 원시 데이터 만 PHP에서 이것을 설명해야합니다
Dan Hanly

열 유형이 필요한 경우 여기를 참조하십시오 forums.whirlpool.net.au/archive/526795
RichardTheKiwi

독자의 경우 선택된 답변에는 결과를 반복해야합니다. 그러나 더 나은 해결책이 있습니다. stackoverflow.com/a/1197424/5079380
Amr ElAdawy

1
@DanHanly-기술적으로 MYSQL 쿼리 (PHP)는 셀 값 의 문자열 표현 을 반환 합니다 . 32 비트 정수의 데이터베이스에 저장된 실제 셀 값은 자릿수가 아닌 32 비트 정수입니다. .
ToolmakerSteve

내가 사용하는 경우 나를 위해, $conn->query("your query")내가 문자열로 정수 필드를 가지고 있지만, 내가 사용하는 경우 $conn->prepare("your query")가 데이터베이스에 있었던 것처럼 내가 매개 변수를 가지고
바 Tzadok

답변:


129

PHP를 사용하여 MySQL 데이터베이스에서 데이터를 선택하면 데이터 유형이 항상 문자열로 변환됩니다. 다음 코드를 사용하여 정수로 다시 변환 할 수 있습니다.

$id = (int) $row['userid'];

또는 기능을 사용하여 intval():

$id = intval($row['userid']);

79
Postgres 배경에서 MySQL로 왔을 때 이것이 엉덩이에 큰 고통이라고 말할 필요가 있다고 생각합니다. Postgres에서 행을 가져올 때 행 배열의 요소에 적절한 데이터 유형이 있는지 확인하십시오. 이제 모든 요소를 ​​원하는 데이터 유형으로 수동 캐스트하는 코드를 작성해야합니다.
GordonM

25
방금 동일한 스키마 및 데이터베이스 서버에서 Laravel 및 Mysql을 사용하여 Windows에서 일부 테스트를 수행했습니다. Windows에서는 기본 키가 정수로 리턴되고 Linux에서는 문자열입니다.
AturSams

좋습니다.하지만 수천 개의 필드를 검색 할 수 있다면 어떨까요? 이 프로세스는 시간이 걸립니다.. 예를 들어 각 게시물의 뷰 수를 검색 한 다음 테이블에 모든 게시물을 인쇄하면 사용자가 View asc 및 desc로 정렬 할 수 있지만 "1"에서 "9로 정렬 할 수 있습니다. "또는"9 "-"1 "이므로 처음에는"9999 ","91 ","8111 ","7 "등을
가질 수 있습니다

@zehelvion 이것에 대한 해결책을 찾은 적이 있습니까?
Felipe Francisco

2
리턴 된 모든 필드는 문자열 OR NULL 입니다.
Liam

73

PHP에는 mysqlnd (네이티브 드라이버)를 사용하십시오.

Ubuntu를 사용하는 경우 :

sudo apt-get install php5-mysqlnd
sudo service apache2 restart

Centos를 사용하는 경우 :

sudo yum install php-mysqlnd
sudo service httpd restart

원시 드라이버는 정수 유형을 적절하게 리턴합니다.

편집하다:

@Jeroen이 지적 했듯이이 방법은 기본적으로 PDO에서만 작동합니다.
@LarsMoelleken이 지적했듯이 MYSQLI_OPT_INT_AND_FLOAT_NATIVE 옵션을 true로 설정하면이 메소드는 mysqli와 함께 작동합니다.

예:

$mysqli = mysqli_init();
$mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, TRUE);

이 단계에 대한 증거가 없습니다. mysqlnd와 mysqli로 실행하면 분명히 문자열 값이 반환됩니다.
Jeroen

@Jeroen 확실합니까? 사용 가능한 많은 문서가 있습니다. stackoverflow.com/questions/1197005/…
advait

예. 아래의 의견도보십시오. 이것을 직접 테스트 했습니까? 지금 보듯이 mysqlnd조차도 준비된 명령문을 사용하면 적절한 유형 만 반환합니다. 예 : $link = mysqli_connect('localhost', 'root', ''); mysqli_set_charset($link,'utf8'); $result = mysqli_query($link,'SELECT CAST(\'3.51\' AS DECIMAL(3,2))'); $row = mysqli_fetch_assoc($result); var_dump($row);반환 : array(1) { ["CAST('3.51' AS DECIMAL(3,2))"]=> string(4) "3.51" }
Jeroen

1
내가 그것을 이해하는 방법이 아니라 PDO 및 Mysqli와 동일하게 작동해야합니다. 주석에 위의 게시물에 게시 된 링크조차도 OP가 작성한 인라인 쿼리가 아니라 준비된 명령문으로 만 작동한다고 명시되어 있습니다. 해당 페이지에서 인용 : 하지만이 :-( 만 (PHP 5.3 버전이 mysqlnd (그리고 오래된 libmysql)로 컴파일 제공) PHP 5.3이며, 오직 준비된 명령문의 경우 것 같다
제론

7
mysqli에 "MYSQLI_OPT_INT_AND_FLOAT_NATIVE"를 사용할 수도 있습니다
Lars Moelleken

20

내가 찾은 가장 쉬운 해결책 :

json_encode가 숫자처럼 보이는 값에 실제 숫자를 사용하도록 할 수 있습니다.

json_encode($data, JSON_NUMERIC_CHECK) 

(PHP 5.3.3부터)

또는 ID를 int로 캐스팅 할 수 있습니다.

$row = $result->fetch_assoc();
$id = (int) $row['userid'];

1
json_encode가능한 경우 문자열을 int로 캐스팅 하는 것은 현미경을 사용하여 손톱을 질식시키는 것과 같습니다.
LibertyPaul

7
우편 번호와 전화 번호가 모두 손상됩니다. 앱에 버그를 도입하는 좋은 방법입니다. 솔루션은 반드시 mysql 열 데이터 유형을 존중해야하며 값을 추측하지 않아야합니다.
Max Cuttins

1
맥스 커틴 스, 포인트가 유효합니다. 그러나 DB에서 예상되는 모든 데이터 유형을 고려할 수 있으면이 방법을 사용하는 것이 좋습니다.
Ifedi Okonkwo

1
'06'과 같은 ID가 있으면 언젠가 아플 것입니다. 이 플래그는 6으로 변환합니다. ID가 0을 계속 유지해야하기 때문에 잘못되었습니다.
Hassan Dad Khan

UNIX_TIMESTAMP()예를 들어에 의해 생성 된 값에 대한 훌륭한 솔루션입니다 .
David

18

내 솔루션은 쿼리 결과를 전달 $rs하고 캐스팅 된 데이터의 assoc 배열을 반환으로 얻는 것입니다.

function cast_query_results($rs) {
    $fields = mysqli_fetch_fields($rs);
    $data = array();
    $types = array();
    foreach($fields as $field) {
        switch($field->type) {
            case 3:
                $types[$field->name] = 'int';
                break;
            case 4:
                $types[$field->name] = 'float';
                break;
            default:
                $types[$field->name] = 'string';
                break;
        }
    }
    while($row=mysqli_fetch_assoc($rs)) array_push($data,$row);
    for($i=0;$i<count($data);$i++) {
        foreach($types as $name => $type) {
            settype($data[$i][$name], $type);
        }
    }
    return $data;
}

사용법 예 :

$dbconn = mysqli_connect('localhost','user','passwd','tablename');
$rs = mysqli_query($dbconn, "SELECT * FROM Matches");
$matches = cast_query_results($rs);
// $matches is now a assoc array of rows properly casted to ints/floats/strings

2
'NULL'을 제외한 훌륭한 솔루션은 settype () 함수에서 사용하는 변수 유형입니다. 따라서 코드는 데이터베이스에서 반환 된 모든 NULL 값 (gettype () == 'NULL'인 값)을 ''값을 가진 'string'유형, 0 값을 가진 '정수'유형 또는 0.0 값을 가진 'float'유형으로 변경합니다. is_null ($ data [$ i] [$ name])이 true이면 settype을 호출 할 필요가 없습니다.
Winter Dragoness 2018 년

나는 mastermind의 기술을 좋아하지만 코딩이 더 간단 할 수 있습니다 .
ToolmakerSteve

13

아니요. 테이블에 정의 된 데이터 유형에 관계없이 PHP의 MySQL 드라이버는 항상 행 값을 문자열로 제공합니다.

ID를 int로 캐스팅해야합니다.

$row = $result->fetch_assoc();
$id = (int) $row['userid'];

6
이 행동에 대한 책임은 (직접적으로) PHP가 아니며 데이터베이스 드라이버입니다. PHP의 Postgres 데이터베이스와 인터페이스하는 경우 적절한 데이터 유형을 다시 얻을 수 있습니다.
GordonM

5

특히 쿼리 결과가 브라우저에서 자바 스크립트로 전달 될 때 Chad의 답변이 마음에 듭니다. Javascript는 숫자와 같은 엔티티를 숫자로 깔끔하게 처리하지만 숫자와 같은 엔티티를 문자열로 처리하려면 추가 작업이 필요합니다. 즉, parseInt 또는 parseFloat를 사용해야합니다.

Chad의 솔루션을 기반으로 나는 이것을 사용하며 종종 내가 정확히 필요한 것이므로 자바 스크립트에서 쉽게 처리 할 수 ​​있도록 JSON으로 인코딩 할 수있는 구조를 만듭니다.

while ($row = $result->fetch_assoc()) {
    // convert numeric looking things to numbers for javascript
    foreach ($row as &$val) {
        if (is_numeric($val))
            $val = $val + 0;
    }
}

0에 숫자 문자열을 추가하면 PHP에서 숫자 유형이 생성되고 유형이 올바르게 식별되므로 부동 소수점 숫자가 정수로 잘리지 않습니다.


5

연결 PDO::ATTR_EMULATE_PREPARES이로 설정되어 있을 때 발생 true합니다.

그러나 false매개 변수를 두 번 이상 사용할 수 없도록 설정하십시오 . 나는 그것이 다시 오는 오류 메시지의 품질에도 영향을 미친다고 생각합니다.


2

당신은 이것을 할 수 있습니다 ...

  1. mysql_fetch_field ()
  2. mysqli_result :: fetch_field_direct 또는
  3. PDOStatement :: getColumnMeta ()

... 사용하려는 확장 프로그램에 따라 다릅니다. 첫 번째는 mysql 확장이 더 이상 사용되지 않기 때문에 권장되지 않습니다. 세 번째는 여전히 실험 중입니다.

이 하이퍼 링크의 주석은 데이터베이스에서 기존의 일반 문자열에서 원래 유형으로 유형을 설정하는 방법을 설명하는 데 유용합니다.

일부 프레임 워크는이를 추상화합니다 (CodeIgniter가 제공 $this->db->field_data()).

결과 행을 반복 하고 각각에 is_numeric () 을 사용하는 것과 같이 추측을 할 수도 있습니다 . 다음과 같은 것 :

foreach($result as &$row){
 foreach($row as &$value){
  if(is_numeric($value)){
   $value = (int) $value;
  }       
 }       
}

이것은 숫자처럼 보이는 것을 1로 바꿀 것입니다 ... 완전히 완벽하지는 않습니다.


수레에는 작동하지 않습니다. 그들은 is_numeric 테스트를 통과합니다. 먼저 수레를 테스트해야합니다.
Martin van Driel

@MartinvanDriel 또는 숫자 만 포함하지만 문자열이어야하는 문자열
treeface

@MartinvanDriel 추가 시도 :if (is_float()) { $value = (float)$value; }
adjwilli

2

내 프로젝트에서는 일반적으로로 검색된 데이터를 "필터링"하는 외부 함수를 사용합니다 mysql_fetch_assoc.

어떤 데이터 유형이 저장되어 있는지 이해하기 쉽게 테이블의 필드 이름을 바꿀 수 있습니다.

예를 들어, 각 숫자 필드에 특별한 접미사를 추가 할 수있는 경우 useridINT(11)당신이 그것을 이름을 바꿀 수 있습니다 userid_i또는 인 경우 UNSIGNED INT(11)이름을 바꿀 수 있습니다 userid_u. 이 시점에서 연관 배열 (으로 검색 mysql_fetch_assoc) 을 입력으로 수신하고 특수한 "키"로 저장된 "값"에 캐스트를 적용 하는 간단한 PHP 함수를 작성할 수 있습니다 .


1

준비된 명령문이 사용되면 적절한 유형이 int입니다. 이 코드는 각 행이 연관 배열 인 행 배열을 반환합니다. if fetch_assoc()가 모든 행에 대해 호출되었지만 유형 정보는 유지됩니다.

function dbQuery($sql) {
    global $mysqli;

    $stmt = $mysqli->prepare($sql);
    $stmt->execute();
    $stmt->store_result();

    $meta = $stmt->result_metadata();
    $params = array();
    $row = array();

    while ($field = $meta->fetch_field()) {
      $params[] = &$row[$field->name];
    }

    call_user_func_array(array($stmt, 'bind_result'), $params);

    while ($stmt->fetch()) {
      $tmp = array();
      foreach ($row as $key => $val) {
        $tmp[$key] = $val;
      }
      $ret[] = $tmp;
    }

    $meta->free();
    $stmt->close();

    return $ret;
}

1

MySQL은 다른 많은 언어를위한 드라이버를 가지고 있는데, 데이터를 문자열로 변환하여 데이터를 "표준화"하고 사용자가 값을 int 또는 다른 것으로 타입 캐스트 할 수 있도록합니다.


1
프리미티브 유형이 거의 "표준"이라고 생각합니까? 언어 별 드라이버가 해당 언어의 요구를 충족시킬 수 없다면 매우 실망 스럽다고 말할 수 있습니다.
Chung

1

내 경우에는 mysqlnd.so확장이 설치되었습니다. 그러나 나는하지 않았다 pdo_mysqlnd.so. 그래서, 문제는 대체하여 해결했다 pdo_mysql.so으로 pdo_mysqlnd.so.


0

나는 mastermind의 기술을 좋아 하지만 코딩이 더 간단 할 수 있습니다.

function cast_query_results($result): array
{
    if ($result === false)
      return null;

    $data = array();
    $fields = $result->fetch_fields();
    while ($row = $result->fetch_assoc()) {
      foreach ($fields as $field) {
        $fieldName = $field->name;
        $fieldValue = $row[$fieldName];
        if (!is_null($fieldValue))
            switch ($field->type) {
              case 3:
                $row[$fieldName] = (int)$fieldValue;
                break;
              case 4:
                $row[$fieldName] = (float)$fieldValue;
                break;
              // Add other type conversions as desired.
              // Strings are already strings, so don't need to be touched.
            }
      }
      array_push($data, $row);
    }

    return $data;
}

또한 결과 집합이 아닌 false를 반환하는 쿼리 검사를 추가했습니다.
그리고 null 값을 가진 필드가있는 행을 확인합니다.
그리고 원하는 유형이 문자열이라면, 나는 이미 문자열입니다.


나는 이것을 대부분의 PHP 코드에서 사용하는 것을 귀찮게하지 않습니다. 나는 단지 PHP의 자동 유형 변환에 의존합니다. 그러나 많은 양의 데이터를 쿼리하고 산술 계산을 수행하는 경우 최적의 유형으로 미리 캐스팅하는 것이 합리적입니다.

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