gpt4 book ai didi

mysql - 如何检查 INSERT 在存储函数中是否运行良好?

转载 作者:可可西里 更新时间:2023-11-01 06:37:14 25 4
gpt4 key购买 nike

我正在创建一个应该向表中插入新行的存储函数。该表中还有一个唯一的列。

我如何检查是否一切顺利,是否真的插入了行?

我如何才能准确检查是否找到了这个唯一的列(例如 - 尝试添加重复值)?

最佳答案

您可以检查 LAST_INSERT_ID() 函数和 INSERT IGNORE。

如果 INSERT IGNORE 成功,您将获得返回的主键。让我们创建一个具有自动递增主键和名称唯一键的表。

use test
DROP TABLE IF EXISTS nametable;
CREATE TABLE nametable
(
id int not null auto_increment,
name varchar(20) not null,
primary key (id),
unique key (name)
);
DELIMITER $$
DROP FUNCTION IF EXISTS `test`.`InsertName` $$
CREATE FUNCTION `test`.`InsertName` (newname VARCHAR(20)) RETURNS INT
BEGIN
INSERT IGNORE INTO test.nametable (name) VALUES (newname);
RETURN LAST_INSERT_ID();
END $$
DELIMITER ;
SELECT InsertName('rolando');
SELECT InsertName('rolando');
SELECT InsertName('pamela');
SELECT InsertName('pamela');
SHOW CREATE TABLE test.nametable\G
SELECT * FROM test.nametable;

这是正在运行的示例:

mysql> use test
Database changed
mysql> DROP TABLE IF EXISTS nametable;
Query OK, 0 rows affected (0.04 sec)

mysql> CREATE TABLE nametable
-> (
-> id int not null auto_increment,
-> name varchar(20) not null,
-> primary key (id),
-> unique key (name)
-> );
Query OK, 0 rows affected (0.07 sec)

mysql> DELIMITER $$
mysql> DROP FUNCTION IF EXISTS `test`.`InsertName` $$
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION `test`.`InsertName` (newname VARCHAR(20)) RETURNS INT
-> BEGIN
-> INSERT IGNORE INTO test.nametable (name) VALUES (newname);
-> RETURN LAST_INSERT_ID();
-> END $$
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> SELECT InsertName('rolando');
+-----------------------+
| InsertName('rolando') |
+-----------------------+
| 1 |
+-----------------------+
1 row in set (0.03 sec)

mysql> SELECT InsertName('rolando');
+-----------------------+
| InsertName('rolando') |
+-----------------------+
| 0 |
+-----------------------+
1 row in set (0.02 sec)

mysql> SELECT InsertName('pamela');
+----------------------+
| InsertName('pamela') |
+----------------------+
| 3 |
+----------------------+
1 row in set (0.02 sec)

mysql> SELECT InsertName('pamela');
+----------------------+
| InsertName('pamela') |
+----------------------+
| 0 |
+----------------------+
1 row in set (0.03 sec)

mysql> SHOW CREATE TABLE test.nametable\G
*************************** 1. row ***************************
Table: nametable
Create Table: CREATE TABLE `nametable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> SELECT * FROM test.nametable;
+----+---------+
| id | name |
+----+---------+
| 3 | pamela |
| 1 | rolando |
+----+---------+
2 rows in set (0.00 sec)

mysql>

如前例所示,您可以检查函数的返回值。非零返回值意味着 INSERT IGNORE 运行良好。零返回值表示重复键,而没有向 mysqld 引入错误号。

这种方法的缺点是您不能返回并使用 id 2 和 4,因为在重复键的情况下尝试 INSERT IGNORE 失败。

让我们尝试另一个使用 INSERT 而不使用 LAST_INSERT_ID() 的不同存储函数设置的示例:

use test
DROP TABLE IF EXISTS nametable;
CREATE TABLE nametable
(
id int not null auto_increment,
name varchar(20) not null,
primary key (id),
unique key (name)
);
DELIMITER $$
DROP FUNCTION IF EXISTS `test`.`InsertName` $$
CREATE FUNCTION `test`.`InsertName` (newname VARCHAR(20)) RETURNS INT
BEGIN
DECLARE rv INT;
SELECT COUNT(1) INTO rv FROM test.nametable WHERE name = newname;
IF rv = 0 THEN
INSERT INTO test.nametable (name) VALUES (newname);
END IF;
RETURN rv;
END $$
DELIMITER ;
SELECT InsertName('rolando');
SELECT InsertName('rolando');
SELECT InsertName('pamela');
SELECT InsertName('pamela');
SHOW CREATE TABLE test.nametable\G
SELECT * FROM test.nametable;

结果如下:

mysql> use test
Database changed
mysql> DROP TABLE IF EXISTS nametable;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> CREATE TABLE nametable
-> (
-> id int not null auto_increment,
-> name varchar(20) not null,
-> primary key (id),
-> unique key (name)
-> );
Query OK, 0 rows affected (0.10 sec)

mysql> DELIMITER $$
mysql> DROP FUNCTION IF EXISTS `test`.`InsertName` $$
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION `test`.`InsertName` (newname VARCHAR(20)) RETURNS INT
-> BEGIN
-> DECLARE rv INT;
-> SELECT COUNT(1) INTO rv FROM test.nametable WHERE name = newname;
-> IF rv = 0 THEN
-> INSERT INTO test.nametable (name) VALUES (newname);
-> END IF;
-> RETURN rv;
-> END $$
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> SELECT InsertName('rolando');
+-----------------------+
| InsertName('rolando') |
+-----------------------+
| 0 |
+-----------------------+
1 row in set (0.04 sec)

mysql> SELECT InsertName('rolando');
+-----------------------+
| InsertName('rolando') |
+-----------------------+
| 1 |
+-----------------------+
1 row in set (0.00 sec)

mysql> SELECT InsertName('pamela');
+----------------------+
| InsertName('pamela') |
+----------------------+
| 0 |
+----------------------+
1 row in set (0.03 sec)

mysql> SELECT InsertName('pamela');
+----------------------+
| InsertName('pamela') |
+----------------------+
| 1 |
+----------------------+
1 row in set (0.00 sec)

mysql> SHOW CREATE TABLE test.nametable\G
*************************** 1. row ***************************
Table: nametable
Create Table: CREATE TABLE `nametable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> SELECT * FROM test.nametable;
+----+---------+
| id | name |
+----+---------+
| 2 | pamela |
| 1 | rolando |
+----+---------+
2 rows in set (0.00 sec)

mysql>

在此示例中,如果 INSERT 成功,则存储函数返回 0,如果名称上有重复键,则返回 1。优势?没有浪费 auto_increment 的 ID 号。劣势?每次执行 SELECT 语句以检查表中已存在的名称。

您可以选择处理重复键的方式。第一种方法让 mysqld 处理 INSERT IGNORE 的条件。第二种方法让存储函数在 INSERT 之前先检查重复键。

关于mysql - 如何检查 INSERT 在存储函数中是否运行良好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5939010/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com