有没有办法将INSERT
行放入包含AUTO_INCREMENT
列的表中,并使用生成的AUTO_INCREMENT
值在同一行中构建另一个字段,在单个行中查询?
我知道可以在两个操作中完成。
我们的产品使用存储为CHAR(16)
的16个字符的数字帐户ID。我们希望将帐户ID存储为单个字段,因为它在我们的数据库中的许多表中被引用,但它由以下部分组成:
AccountType INT(4) UNSIGNED // never less than 1000
AccountNumber INT(10) UNSIGNED AUTO_INCREMENT PRIMARY
AccountSite INT(2) UNSIGNED
为了生成16个字符的accountID字段,将它们连接起来。 AccountType值永远不会小于1000。
我希望能够执行单个INSERT
操作,如果可能的话,在同一查询中生成四个字段。
答案 0 :(得分:2)
我可以用存储过程来显示它。您最终可能只需要表中的1列或2列。但我显示更多(假设文本用户友好的字符串也是如此)。这部分是微不足道的,可以在列数中缩小它。
<强>架构:强>
drop table if exists tX4;
create table tX4
( AccountType INT(4) UNSIGNED not null, -- // never less than 1000
AccountNumber INT(10) AUTO_INCREMENT PRIMARY key,
AccountSite INT(2) UNSIGNED not null,
col4 varchar(50) not null,
weWantThis char(16) not null
);
-- truncate tX4; -- used for testing
存储过程:
DROP PROCEDURE IF EXISTS ins_tX4;
DELIMITER $$
CREATE PROCEDURE ins_tX4
( p_AccountType int,
p_AccountSite int,
p_col4 varchar(50)
)
BEGIN
DECLARE theAI int;
DECLARE sConcatFix char(16);
START TRANSACTION;
insert tX4(AccountType,AccountSite,col4,weWantThis) values (p_AccountType,p_AccountSite,p_col4,'');
set theAI=last_insert_id();
set sConcatFix=concat( lpad(p_AccountType,4,'0'), lpad(theAi,10,'0'), lpad(p_AccountSite,2,'0') );
update tX4 set weWantThis=sConcatFix where AccountNumber=theAI;
COMMIT;
END$$
DELIMITER ;
<强>测试强>
call ins_tX4(1,2,'cat');
select * from tX4;
+-------------+---------------+-------------+------+------------------+
| AccountType | AccountNumber | AccountSite | col4 | weWantThis |
+-------------+---------------+-------------+------+------------------+
| 1 | 1 | 2 | cat | 0001000000000102 |
+-------------+---------------+-------------+------+------------------+
可视化片段:
0001 0000000001 02
分别是AccountType,AI,AccountSite(宽度4,10,2)。
call ins_tX4(8765,42,'Sunday');
select * from tX4;
+-------------+---------------+-------------+--------+------------------+
| AccountType | AccountNumber | AccountSite | col4 | weWantThis |
+-------------+---------------+-------------+--------+------------------+
| 1 | 1 | 2 | cat | 0001000000000102 |
| 8765 | 2 | 42 | Sunday | 8765000000000242 |
+-------------+---------------+-------------+--------+------------------+
列weWantThis
可以用作其他表格中FK的目标。
LPAD()
的手册页(左边填充)。
使用OUT
参数发送回已分配的AI#。请注意,默认情况下参数为IN
个参数。
存储过程:
DROP PROCEDURE IF EXISTS ins_tX4;
DELIMITER $$
CREATE PROCEDURE ins_tX4
( p_AccountType int,
p_AccountSite int,
p_col4 varchar(50),
OUT AI_assigned int
)
BEGIN
DECLARE theAI int;
DECLARE sConcatFix char(16);
-- AI means database-assigned AUTO INCREMENT
set AI_assigned = -1; -- assume an Error condition
START TRANSACTION;
insert tX4(AccountType,AccountSite,col4,weWantThis) values (p_AccountType,p_AccountSite,p_col4,'');
set theAI=last_insert_id();
set sConcatFix=concat( lpad(p_AccountType,4,'0'), lpad(theAi,10,'0'), lpad(p_AccountSite,2,'0') );
update tX4 set weWantThis=sConcatFix where AccountNumber=theAI;
set AI_assigned = theAI; -- the OUT parameter is set to the AI value
COMMIT;
END$$
DELIMITER ;
从mysql环境测试:
set @var1 = -1;
call ins_tX4(22,33,'Monday',@var1);
select @var1;
-- 3
call ins_tX4(333,79,'Tuesday',@var1);
select @var1;
-- 4
从PHP环境进行测试:
由于此问题已标记为PHP
,请参阅用户Matteo Tassinari的答案,如here。
答案 1 :(得分:0)
这可以通过TRANSACTION
完成。
START TRANSACTION;
INSERT INTO accounts (accountType, accountSite) VALUES(1000,10);
UPDATE accounts SET accountID = CONCAT(LPAD(accountType, 4, '0'), LPAD(accountNumber, 10, '0'), LPAD(accountSite, 2, '0')) WHERE accountNumber = LAST_INSERT_ID();
COMMIT;
例如可以在php中执行:
$mysqli = new mysqli(...);
$mysqli->begin_transaction();
$query = "INSERT INTO accounts (accountType, accountSite) VALUES(1000,10);"
$query .= "UPDATE accounts SET accountID = CONCAT(LPAD(accountType, 4, '0'), LPAD(accountNumber, 10, '0'), LPAD(accountSite, 2, '0')) WHERE accountNumber = LAST_INSERT_ID();"
$mysqli->query($query);
$mysqli->commit();