khargoosh khargoosh - 5 months ago 11
PHP Question

Create field from auto increment value on INSERT

Is there a way to

INSERT
a row into a table which contains an
AUTO_INCREMENT
column, and use the resulting
AUTO_INCREMENT
value to construct another field in the same row, in a single query?

I know it can be done in two operations.

Our product uses a 16 character numeric account ID stored as
CHAR(16)
. We like to store the account ID as a single field as it is referenced in many tables throughout our database(s), however it is made up of the following parts:

AccountType INT(4) UNSIGNED // never less than 1000
AccountNumber INT(10) UNSIGNED AUTO_INCREMENT PRIMARY
AccountSite INT(2) UNSIGNED


Which are concatenated in order to produce the 16 character accountID field. The AccountType value is never less than 1000.

I would like to be able to perform a single
INSERT
operation that produces the four fields within the same query, if possible.

Answer

I can show this with a stored procedure. You may in the end only want 1 or 2 columns in the table. But I am showing more (assuming a text user friendly string too). That part is trivial, to shrink it down in column count.

Schema:

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

Stored Procedure:

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 ;

Test:

call ins_tX4(1,2,'cat');

select * from tX4;
+-------------+---------------+-------------+------+------------------+
| AccountType | AccountNumber | AccountSite | col4 | weWantThis       |
+-------------+---------------+-------------+------+------------------+
|           1 |             1 |           2 | cat  | 0001000000000102 |
+-------------+---------------+-------------+------+------------------+

Visualized pieces:

0001 0000000001 02

Which is AccountType, the AI, AccountSite (widths 4,10,2) respectively.

call ins_tX4(8765,42,'Sunday');

select * from tX4;
+-------------+---------------+-------------+--------+------------------+
| AccountType | AccountNumber | AccountSite | col4   | weWantThis       |
+-------------+---------------+-------------+--------+------------------+
|           1 |             1 |           2 | cat    | 0001000000000102 |
|        8765 |             2 |          42 | Sunday | 8765000000000242 |
+-------------+---------------+-------------+--------+------------------+

Column weWantThis could be used as the target for an FK from other tables.

Manual page for LPAD() (Left Padding).

Edit

With an OUT parameter to send back the AI # assigned. Note that parameters are IN parameters by default.

Stored Procedure:

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 ;

Test from mysql environment:

set @var1 = -1;

call ins_tX4(22,33,'Monday',@var1);
select @var1;
-- 3

call ins_tX4(333,79,'Tuesday',@var1);
select @var1;
-- 4

Test from a PHP environment:

Because this question is tagged PHP, see an answer like the one here from user Matteo Tassinari.

Comments