목차
MySQL string转成double的定义函数如下:
MySQL 문자열을 double로 변환하는 정의 함수는 다음과 같습니다:
데이터 베이스 MySQL 튜토리얼 MySQL의 놀라운 암시적 변환을 살펴보세요

MySQL의 놀라운 암시적 변환을 살펴보세요

Jan 13, 2021 am 09:20 AM
mysql 암시적 변환

mysql 튜토리얼 칼럼에서는 관련 암시적 변환을 소개합니다

MySQL의 놀라운 암시적 변환을 살펴보세요

더 많은 관련 무료 학습 권장사항: mysql tutorial(동영상)

一, 문제 설명

root@mysqldb 22:12:  [xucl]> show create table t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `id` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

root@mysqldb 22:19:  [xucl]> select * from t1;
+--------------------+
| id                 |
+--------------------+
| 204027026112927605 |
| 204027026112927603 |
| 2040270261129276   |
| 2040270261129275   |
| 100                |
| 101                |
+--------------------+
6 rows in set (0.00 sec)
로그인 후 복사

이상한 현상:

root@mysqldb 22:19:  [xucl]> select * from t1 where id=204027026112927603;
+--------------------+
| id                 |
+--------------------+
| 204027026112927605 |
| 204027026112927603 |
+--------------------+
2 rows in set (0.00 sec)
로그인 후 복사

MySQL의 놀라운 암시적 변환을 살펴보세요

뭐야 당연히 204027026112927603인데 왜 204027026112927605도 나왔는지

두번째, 소스코드 설명

스택콜 관계는 다음과 같습니다:

MySQL의 놀라운 암시적 변환을 살펴보세요

어디 < code>JOIN::exec()는 실행 진입점, Arg_comparator::compare_real()은 동등성 판단을 위한 함수로 정의는 다음과 같습니다JOIN::exec()是执行的入口,Arg_comparator::compare_real()是进行等值判断的函数,其定义如下

int Arg_comparator::compare_real()
{
  /*
    Fix yet another manifestation of Bug#2338. &#39;Volatile&#39; will instruct
    gcc to flush double values out of 80-bit Intel FPU registers before
    performing the comparison.
  */
  volatile double val1, val2;
  val1= (*a)->val_real();
  if (!(*a)->null_value)
  {
    val2= (*b)->val_real();
    if (!(*b)->null_value)
    {
      if (set_null)
        owner->null_value= 0;
      if (val1 < val2)  return -1;
      if (val1 == val2) return 0;
      return 1;
    }
  }
  if (set_null)
    owner->null_value= 1;
  return -1;
}
로그인 후 복사

比较步骤如下图所示,逐行读取t1表的id列放入val1,而常量204027026112927603存在于cache中,类型为double类型(2.0402702611292762E+17),所以到这里传值给val2后val2=2.0402702611292762E+17。

MySQL의 놀라운 암시적 변환을 살펴보세요

当扫描到第一行时,204027026112927605转成doule的值为2.0402702611292762e17,等式成立,判定为符合条件的行,继续往下扫描,同理204027026112927603也同样符合

MySQL의 놀라운 암시적 변환을 살펴보세요

如何检测string类型的数字转成doule类型是否溢出呢?这里经过测试,当数字超过16位以后,转成double类型就已经不准确了,例如20402702611292711会表示成20402702611292712(如图中val1)

MySQL의 놀라운 암시적 변환을 살펴보세요

MySQL의 놀라운 암시적 변환을 살펴보세요

MySQL string转成double的定义函数如下:

{
  char buf[DTOA_BUFF_SIZE];
  double res;
  DBUG_ASSERT(end != NULL && ((str != NULL && *end != NULL) ||
                              (str == NULL && *end == NULL)) &&
              error != NULL);

  res= my_strtod_int(str, end, error, buf, sizeof(buf));
  return (*error == 0) ? res : (res < 0 ? -DBL_MAX : DBL_MAX);
}
로그인 후 복사

真正转换函数my_strtod_int

/*
  strtod for IEEE--arithmetic machines.
 
  This strtod returns a nearest machine number to the input decimal
  string (or sets errno to EOVERFLOW). Ties are broken by the IEEE round-even
  rule.
 
  Inspired loosely by William D. Clinger&#39;s paper "How to Read Floating
  Point Numbers Accurately" [Proc. ACM SIGPLAN &#39;90, pp. 92-101].
 
  Modifications:
 
   1. We only require IEEE (not IEEE double-extended).
   2. We get by with floating-point arithmetic in a case that
     Clinger missed -- when we&#39;re computing d * 10^n
     for a small integer d and the integer n is not too
     much larger than 22 (the maximum integer k for which
     we can represent 10^k exactly), we may be able to
     compute (d*10^k) * 10^(e-k) with just one roundoff.
   3. Rather than a bit-at-a-time adjustment of the binary
     result in the hard case, we use floating-point
     arithmetic to determine the adjustment to within
     one bit; only in really hard cases do we need to
     compute a second residual.
   4. Because of 3., we don&#39;t need a large table of powers of 10
     for ten-to-e (just some small tables, e.g. of 10^k
     for 0 <= k <= 22).
*/
로그인 후 복사

비교 단계는 다음과 같습니다. 그림과 같이 t1 테이블의 id 열을 한 행씩 읽어서 val1에 배치하고 캐시에 상수 204027026112927603이 존재하고 유형이 double(2.0402702611292762E+17)이므로 통과한 후 여기서 val2 값은 val2=2.0402702611292762E+17 입니다.

MySQL의 놀라운 암시적 변환을 살펴보세요

첫 번째 행을 스캔하면 204027026112927605를 double로 변환한 값이 2.0402702611292762e17이 됩니다. 방정식이 성립되고 정규 행으로 판단됩니다. 마찬가지로 계속해서 스캔하면 204027026112927603도 일치합니다. ="rich_pages" src="https://img.php.cn/upload/article/000/000/052/7c4b6d4d87941f0fc37f0c115a3cf15e-3.jpg" alt="MySQL의 놀라운 암시적 변환을 살펴보세요"/>

감지하는 방법 string형 숫자로 변환 double형이 오버플로 되나요? 여기서 테스트해본 결과 숫자가 16자리를 초과하면 double형으로의 변환이 더 이상 정확하지 않습니다. 예를 들어 20402702611292712(그림에서는 val1)로 표시됩니다. )

    MySQL의 놀라운 암시적 변환을 살펴보세요
  1. MySQL의 놀라운 암시적 변환을 살펴보세요

    MySQL 문자열을 double로 변환하는 정의 함수는 다음과 같습니다:

    root@mysqldb 23:30:  [xucl]> select * from t1 where id=2040270261129276;
    +------------------+
    | id               |
    +------------------+
    | 2040270261129276 |
    +------------------+
    1 row in set (0.00 sec)
    
    root@mysqldb 23:30:  [xucl]> select * from t1 where id=101;
    +------+
    | id   |
    +------+
    | 101  |
    +------+
    1 row in set (0.00 sec)
    로그인 후 복사

    실제 변환 함수 my_strtod_int는 dtoa.c에 있습니다(너무 복잡합니다. 댓글)
  2. root@mysqldb 22:19:  [xucl]> select * from t1 where id=&#39;204027026112927603&#39;;
    +--------------------+
    | id                 |
    +--------------------+
    | 204027026112927603 |
    +--------------------+
    1 row in set (0.01 sec)
    로그인 후 복사
  3. 이 경우에는 우리 테스트에서 Overflow가 없었습니다.

    1、If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe
    <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
    2、If both arguments in a comparison operation are strings, they are compared as strings.
    3、If both arguments are integers, they are compared as integers.
    4、Hexadecimal values are treated as binary strings if not compared to a number.
    5、If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a
    constant, the constant is converted to a timestamp before the comparison is performed. This is
    done to be more ODBC-friendly. This is not done for the arguments to IN(). To be safe, always
    use complete datetime, date, or time strings when doing comparisons. For example, to achieve best
    results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to
    the desired data type.
    A single-row subquery from a table or tables is not considered a constant. For example, if a subquery
    returns an integer to be compared to a DATETIME value, the comparison is done as two integers.
    The integer is not converted to a temporal value. To compare the operands as DATETIME values,
    use CAST() to explicitly convert the subquery value to DATETIME.
    6、If one of the arguments is a decimal value, comparison depends on the other argument. The
    arguments are compared as decimal values if the other argument is a decimal or integer value, or as
    floating-point values if the other argument is a floating-point value.
    7、In all other cases, the arguments are compared as floating-point (real) numbers.
    로그인 후 복사
    의 결과는 예상과 일치하며, 이 경우 올바른 쓰기는 rrreee이어야 합니다. 3. 결론
  4. 암시적 유형 변환을 피하세요. 암시적 변환 유형에는 주로 일관성 없는 필드 유형이 포함됩니다. in 매개변수에는 여러 유형, 문자 세트 유형 또는 일관성 없는 데이터 정렬 규칙이 포함됩니다.
  5. 암시적 유형 변환으로 인해 사용이 불가능해질 수 있습니다. 인덱스, 부정확한 쿼리 결과 등이 있으므로 🎜🎜🎜🎜🎜 사용 시 주의 깊게 선별해야 합니다. 필드 정의 시 숫자 유형은 int 또는 bigint로 정의하는 것이 좋습니다. 유형, 문자 집합 및 조합 규칙을 일관되게 유지해야 합니다🎜🎜🎜🎜🎜🎜마지막으로 공식 웹사이트에서 암시적 유형 변환에 대한 지침을 게시하세요🎜 🎜🎜🎜rrreee

    위 내용은 MySQL의 놀라운 암시적 변환을 살펴보세요의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

PHP에서 MySQL 백업 및 복원을 사용하는 방법은 무엇입니까? PHP에서 MySQL 백업 및 복원을 사용하는 방법은 무엇입니까? Jun 03, 2024 pm 12:19 PM

PHP에서 MySQL 데이터베이스를 백업하고 복원하는 작업은 다음 단계에 따라 수행할 수 있습니다. 데이터베이스 백업: mysqldump 명령을 사용하여 데이터베이스를 SQL 파일로 덤프합니다. 데이터베이스 복원: mysql 명령을 사용하여 SQL 파일에서 데이터베이스를 복원합니다.

PHP에서 MySQL 쿼리 성능을 최적화하는 방법은 무엇입니까? PHP에서 MySQL 쿼리 성능을 최적화하는 방법은 무엇입니까? Jun 03, 2024 pm 08:11 PM

선형 복잡성에서 로그 복잡성까지 조회 시간을 줄이는 인덱스를 구축하여 MySQL 쿼리 성능을 최적화할 수 있습니다. SQL 삽입을 방지하고 쿼리 성능을 향상하려면 PREPAREDStatements를 사용하세요. 쿼리 결과를 제한하고 서버에서 처리되는 데이터의 양을 줄입니다. 적절한 조인 유형 사용, 인덱스 생성, 하위 쿼리 사용 고려 등 조인 쿼리를 최적화합니다. 쿼리를 분석하여 병목 현상을 식별하고, 캐싱을 사용하여 데이터베이스 로드를 줄이고, 오버헤드를 최소화합니다.

PHP를 사용하여 MySQL 테이블에 데이터를 삽입하는 방법은 무엇입니까? PHP를 사용하여 MySQL 테이블에 데이터를 삽입하는 방법은 무엇입니까? Jun 02, 2024 pm 02:26 PM

MySQL 테이블에 데이터를 삽입하는 방법은 무엇입니까? 데이터베이스에 연결: mysqli를 사용하여 데이터베이스에 대한 연결을 설정합니다. SQL 쿼리 준비: 삽입할 열과 값을 지정하는 INSERT 문을 작성합니다. 쿼리 실행: query() 메서드를 사용하여 삽입 쿼리를 실행하면 확인 메시지가 출력됩니다.

PHP를 사용하여 MySQL 테이블을 만드는 방법은 무엇입니까? PHP를 사용하여 MySQL 테이블을 만드는 방법은 무엇입니까? Jun 04, 2024 pm 01:57 PM

PHP를 사용하여 MySQL 테이블을 생성하려면 다음 단계가 필요합니다. 데이터베이스에 연결합니다. 데이터베이스가 없으면 작성하십시오. 데이터베이스를 선택합니다. 테이블을 생성합니다. 쿼리를 실행합니다. 연결을 닫습니다.

PHP에서 MySQL 저장 프로시저를 사용하는 방법은 무엇입니까? PHP에서 MySQL 저장 프로시저를 사용하는 방법은 무엇입니까? Jun 02, 2024 pm 02:13 PM

PHP에서 MySQL 저장 프로시저를 사용하려면: PDO 또는 MySQLi 확장을 사용하여 MySQL 데이터베이스에 연결합니다. 저장 프로시저를 호출하는 문을 준비합니다. 저장 프로시저를 실행합니다. 결과 집합을 처리합니다(저장 프로시저가 결과를 반환하는 경우). 데이터베이스 연결을 닫습니다.

MySQL 8.4에서 mysql_native_password가 로드되지 않음 오류를 수정하는 방법 MySQL 8.4에서 mysql_native_password가 로드되지 않음 오류를 수정하는 방법 Dec 09, 2024 am 11:42 AM

MySQL 8.4(2024년 최신 LTS 릴리스)에 도입된 주요 변경 사항 중 하나는 &quot;MySQL 기본 비밀번호&quot; 플러그인이 더 이상 기본적으로 활성화되지 않는다는 것입니다. 또한 MySQL 9.0에서는 이 플러그인을 완전히 제거합니다. 이 변경 사항은 PHP 및 기타 앱에 영향을 미칩니다.

오라클 데이터베이스와 mysql의 차이점 오라클 데이터베이스와 mysql의 차이점 May 10, 2024 am 01:54 AM

Oracle 데이터베이스와 MySQL은 모두 관계형 모델을 기반으로 하는 데이터베이스이지만 호환성, 확장성, 데이터 유형 및 보안 측면에서 Oracle이 우수하고, MySQL은 속도와 유연성에 중점을 두고 중소 규모 데이터 세트에 더 적합합니다. ① Oracle은 광범위한 데이터 유형을 제공하고, ② 고급 보안 기능을 제공하고, ③ 엔터프라이즈급 애플리케이션에 적합하고, ① MySQL은 NoSQL 데이터 유형을 지원하고, ② 보안 조치가 적고, ③ 중소 규모 애플리케이션에 적합합니다.

C 언어에서 bool을 사용하는 방법 C 언어에서 bool을 사용하는 방법 May 09, 2024 pm 01:00 PM

C 언어의 bool 유형은 true/false를 나타내며 값은 1(true) 또는 0(false)입니다. bool is_true = true;를 사용하여 부울 변수를 선언하고 초기화하거나 true/false 키워드를 사용할 수 있습니다. Bool 변수는 논리적 NOT, AND, OR 및 XOR 연산을 사용할 수 있습니다. 부울 표현식은 조건문과 루프에 사용됩니다. bool 유형은 암시적으로 int 유형으로 변환될 수 있습니다(1: true, 0: false). int 유형은 암시적으로 bool 유형(0이 아닌 경우: true, 0: false)으로 변환될 수도 있습니다.

See all articles