>  기사  >  데이터 베이스  >  MySQL 프로시저 매개변수가 NULL 문제 분석입니다.

MySQL 프로시저 매개변수가 NULL 문제 분석입니다.

高洛峰
高洛峰원래의
2016-12-02 14:48:261577검색

최근 프로시저를 작성할 때 흥미로운 점을 발견했습니다. Mysql 프로시저에는 매개변수를 전달할 때 일부 "불법적인" 매개변수를 처리하는 고유한 방법이 있습니다. 예를 들어 원래 int로 정의된 매개변수를 null
로 전달하면 MySQL 프로시저가 정상적으로 실행됩니다.
라이브러리 테이블 구조:
데이터베이스 db5 생성;

db5 사용;

존재하는 경우 테이블 삭제;
테이블 t 생성(
id int 기본 키 auto_increment ,
value int
);

테이블 t2 만들기(
id int 기본 키 auto_increment,
value float
);
프로시저 만들기:
구분 기호 //
CREATE PROCEDURE p14 (IN 매개변수1 INT)
BEGIN
DECLARE 변수1 INT;
SET 변수1 = 매개변수1 + 1;
INSERT INTO t(값) VALUES(변수1);
END;
//
구분자 ;

실행 결과:


mysql> call p14(5);
쿼리 OK, 1행 영향(0.02) 초)

mysql> select * from t;
+----+-------+
| id |
+----+- ------+
| 2 | 6 |
+----+-------+
세트의 1개 행(0.00초)

mysql> ; p14(null) 호출;
쿼리 확인, 1개 행이 영향을 받음(0.04초)

mysql> select * from t;
+----+------+
| ID | 값 |
+------+
| 2 | 6 |
| 3 | ------+
세트의 2개 행(0.00초)


parameter1이 5와 같게 전달되면 6이 테이블에 삽입되고 데이터가 정상이라는 것을 알고 계셨습니까? .
parameter1이 null로 전달되면 테이블에 NULL이 삽입되는 이유는 무엇입니까?

이 점에 대해서는 변수를 선언하는 문을 보면 다음과 같이 설명되어 있습니다. 선언 문은 지역 변수를 선언하는 데 사용됩니다. 변수에 기본값을 제공하려면 DEFAULT 절을 포함하세요. 값은 표현식으로 지정할 수 있으며 상수일 필요는 없습니다. DEFAULT 절이 없는 경우 초기값은 NULL입니다.

위에서 새로운 질문이 생깁니다: NULL=NULL+1? 하하, 이때 SET 변수1 = 매개변수1 + 1;에 대한 합리적인 설명은 무엇입니까?

왕 선생님의 설명은 다음과 같습니다(두 번째는 매우 고전적입니다~~):
1 null+1=null
null은 "포인터"처럼 동작하기 때문입니다. 이는 "0 주소 콘텐츠"를 가리키며, 이 콘텐츠가 "null"인 경우 null로 표시됩니다. 그렇기 때문에 INT를 지정하는 것도 비어 있습니다. 그러나 "content"에 값이 있으면 비어 있지 않습니다. MYSQL의 경우 이 주소의 내용이 저장될 때 "임의의 숫자" 또는 0입니다.


2 A=B+1이면 B가 null인 경우에만 A가 NULL이고, SET A=B+1이면 SET(B+1)로 이해될 수 있습니까? A는 '현재'에서 대체되었습니다. A가 누구인지는 중요하지 않습니다. 중요한 것은 B+1입니다.
이 아이디어는 주로 SET를 분리할 수 없기 때문에 확인되지 않았으며 mysql5의 문서에서는 이 명령문을 지원하지만 영어 버전에서는 "replacement"를 사용합니다. , 중국어의 "세트" 표현이 아니라 그 의미가 더 가깝게 느껴집니다! (SET)

새로운 질문: A=1/B이고 B=0일 때 성공적으로 실행될 수 있습니까?

mysql>

구분자 //
CREATE PROCEDURE p15 (IN 매개변수1 INT)
BEGIN
변수2 선언 float(5,3);
SET 변수2 = 1/ 매개변수1;
INSERT INTO t2(값) VALUES(변수2);
END;
//
구분자;

실행 결과:

mysql> call p15(0);
쿼리 확인, 1개 행 영향(0.03초)

mysql> select * from t2;
+----+---------+
| ID | 값 |
+----+-------+
| 1 |
+----+-----+
세트의 1개 행(0.00초)

mysql> p15(1) 호출;
쿼리 OK, 1개 행이 영향을 받음(0.03초)

mysql> ;
+----+-------+
| ID | 값 |
+----+-------+
| |
| 2 | 1 |

독자님들도 눈치채셨나요? 이것은 또한 성공적으로 작동합니다. 실제로 이 문제는 mysql의 SQL 서버 모드 매개변수 세부정보에서 찾을 수 있습니다.
MySQL 서버는 다양한 SQL 모드로 작동할 수 있으며, 클라이언트마다 다양한 모드를 적용할 수 있습니다. 이런 방식으로 각 응용 프로그램은 자체 필요에 따라 서버의 작동 모드를 사용자 정의할 수 있습니다.
스키마는 MySQL이 지원해야 하는 SQL 구문과 수행해야 하는 데이터 유효성 검사의 종류를 정의합니다. 이를 통해 다양한 환경 및 다른 데이터베이스 서버에서 MySQL을 더 쉽게 사용할 수 있습니다.
--sql-mode="modes" 옵션으로 mysqld를 시작하여 기본 SQL 모드를 설정할 수 있습니다. 재설정하려는 경우 이 값을 비워 둘 수도 있습니다(--sql-mode = "").
또한 SET [SESSION|GLOBAL] sql_mode='modes' 문을 사용하여 sql_mode 변수를 설정하여 시작 후 SQL 모드를 변경할 수도 있습니다. GLOBAL 변수를 설정하려면 SUPER 권한이 필요하며 해당 시점부터 연결된 모든 클라이언트의 작동에 영향을 미칩니다. SESSION 변수 설정은 현재 클라이언트에만 영향을 미칩니다. 모든 클라이언트는 언제든지 해당 세션의 sql_mode 값을 변경할 수 있습니다.
Modesis는 쉼표(',')로 구분된 일련의 다양한 모드입니다. SELECT @@sql_mode 문을 사용하여 현재 모드를 쿼리할 수 있습니다. 기본값은 비어 있습니다(모드가 설정되지 않음).
STRICT_TRANS_TABLES
모든 스토리지 엔진에 대해 엄격 모드를 활성화합니다. 불법적인 데이터 값은 거부됩니다. 자세한 지침은 나중에 나와 있습니다.
· STRICT_TRANS_TABLES
트랜잭션 스토리지 엔진 및 비트랜잭션 스토리지 엔진에 대해 엄격 모드를 활성화합니다. 자세한 지침은 나중에 나와 있습니다.
엄격 모드는 MySQL이 잘못되거나 누락된 입력 값을 처리하는 방법을 제어합니다. 값이 불법적인 데에는 여러 가지 이유가 있습니다. 예를 들어 데이터 유형이 잘못되었거나 열에 맞지 않거나 범위를 벗어났습니다. 새로 삽입된 행에 DEFAULT 절을 명시적으로 정의하지 않은 열의 값이 없으면 해당 값이 손실됩니다.
트랜잭션 테이블의 경우 STRICT_ALL_TABLES 또는 STRICT_TRANS_TABLES 모드가 활성화되면 문에 잘못된 값이나 누락된 값이 있으면 오류가 발생합니다. 명령문은 폐기되고 롤링됩니다.
비트랜잭션 테이블의 경우 삽입 또는 업데이트의 행 1에 잘못된 값이 있는 경우 두 모드 모두 동일하게 작동합니다. 명령문은 삭제되고 테이블은 변경되지 않은 상태로 유지됩니다. 문이 여러 행을 삽입하거나 수정하고 두 번째 이후 행에 잘못된 값이 발생하면 결과는 어떤 엄격한 옵션이 활성화되어 있는지에 따라 달라집니다.
ERROR_FOR_DIVISION_BY_ZERO
엄격 모드에서 INSERT 또는 UPDATE 중에 0 Division( 또는 MOD(X, 0)), 오류가 발생합니다(그렇지 않으면 경고). 모드가 지정되지 않은 경우 MySQL은 0으로 나눌 때 NULL을 반환합니다. INSERT IGNORE 또는 UPDATE IGNORE에 사용될 경우 MySQL은 0으로 나누기 경고를 생성하지만 작업 결과는 NULL입니다.
다른 매개변수도 있습니다. 독자는 mysql 문서를 참조할 수 있습니다.

sql_mode에 ERROR_FOR_DIVISION_BY_ZERO 매개변수를 추가하면 mysql을 다시 시작합니다
mysql> 'sql_mode';
+---------------+ -- ------------------------------------------------ -- -----------
---------------+
| 변수명
                                                                           ---------------------------------------
------ -- -------+
| sql_mode | STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_
USER,NO_ENGINE_SUBSTITUTION |
+----- -------+--------------- - --------
------------------------- -- ---+
세트의 1개 행(0.00초)

mysql> 1/0 선택;
+------+
| 🎜> +------+
| NULL |
+------+
세트에 행 1개, 경고 1개(0.00초)

1개 표시됨 warning , 이 경고를 살펴보겠습니다:
mysql> show warnings;
+-------+------+------------- -- +
| 레벨 | 코드 |
+-------+------+------------+
| 오류 | 1365 | 0으로 나누기 |
+-------+------+---------------+
1행 설정(0.00초)

mysql>exit
안녕
sql_mode에서 ERROR_FOR_DIVISION_BY_ZERO 매개변수를 제거하면 mysql을 다시 시작하고 다음을 시도하세요.

C:Documents and SettingsAdministrator>net stop mysql
MySQL 서비스가 중지 중입니다.
MySQL 서비스가 성공적으로 중지되었습니다.


C:Documents and SettingsAdministrator>net start mysql

MySQL 서비스가 성공적으로 시작되었습니다.


mysql> 1/0 선택;
+------+
| 1/0 |
+------+
| NULL |
+------+
세트의 1개 행(0.00초)

mysql> 경고 표시;
빈 세트(0.02초)
경고 시간 내용이 비어 있습니다.
이쯤 되면 독자들도 그 이유를 알게 될 것이다. 시간이 나면 다른 데이터베이스를 사용해 보고 이것이 맞는지 확인하세요

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