4
CREATE TRIGGER test1 AFTER INSERT ON `course_metadata_31`
FOR EACH ROW BEGIN
    UPDATE `course_metadata_31`
    SET `articleID` = `articleID` + 1
END;

I am using this approach. When I will insert new entry in course_metadata_31 it should increment articleID too. Because I want articleID as another auto increment column.

What should I do?

informatik01
  • 16,038
  • 10
  • 74
  • 104
John
  • 478
  • 4
  • 12
  • 25
  • You can't have two auto-increment columns. You could use a trigger, but why? Won't one auto-increment column be enough? –  Apr 02 '14 at 22:40
  • Yeah I am using trigger. As written above but it shows error – John Apr 02 '14 at 22:43
  • 1
    I need two auto increment columns – John Apr 02 '14 at 22:43
  • No you don't, since the data is essentially the same. You should be clearer on what you're trying to achieve. –  Apr 02 '14 at 22:51

7 Answers7

3

No idea why you need two columns auto incrementing values, there is no point... but if you insist -
You can accomplish it in a UDF or SP this way you have multiple columns auto incrementing a value.

EXAMPLE #1: STORED PROCEDURE (SP)


Table

CREATE TABLE tests (
    test_id INT(10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
    test_num INT(10) NULL,
    test_name VARCHAR(10) NOT NULL
);



Stored Procedure

DELIMITER $$
CREATE PROCEDURE autoInc (name VARCHAR(10))
    BEGIN
        DECLARE getCount INT(10);

        SET getCount = (
            SELECT COUNT(test_num)
            FROM tests) + 1;

        INSERT INTO tests (test_num, test_name)
            VALUES (getCount, name);
    END$$
DELIMITER ;



Call the SP

CALL autoInc('one');
CALL autoInc('two');
CALL autoInc('three');



Look up the table

SELECT * FROM tests;

+---------+----------+-----------+
| test_id | test_num | test_name |
+---------+----------+-----------+
|       1 |       1  | one       |
|       2 |       2  | two       |
|       3 |       3  | three     |
+---------+----------+-----------+




EXAMPLE #2: USER-DEFINED FUNCTION (UDF)


Table
CREATE TABLE tests (
    test_id INT(10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
    test_num INT(10) NULL,
    test_name VARCHAR(10) NOT NULL
);



User-defined Function

DELIMITER $$
CREATE FUNCTION autoInc ()
    RETURNS INT(10)
    BEGIN
        DECLARE getCount INT(10);

        SET getCount = (
            SELECT COUNT(test_num)
            FROM tests) + 1;

        RETURN getCount;
    END$$
DELIMITER ;



Insert using the UDF

INSERT INTO tests (test_num, test_name) VALUES (autoInc(), 'one');
INSERT INTO tests (test_num, test_name) VALUES (autoInc(), 'two');
INSERT INTO tests (test_num, test_name) VALUES (autoInc(), 'three');



Look up the table

SELECT * FROM tests;

+---------+----------+-----------+
| test_id | test_num | test_name |
+---------+----------+-----------+
|       1 |       1  | one       |
|       2 |       2  | two       |
|       3 |       3  | three     |
+---------+----------+-----------+

These have been tested and verified. I'd personally use the function, it's more flexible.

Thielicious
  • 4,122
  • 2
  • 25
  • 35
  • Thanks for the answer. I can think of 2 reasons someone would want this. 1. As a default value for columns like "ordering" where every time someone inserts a new row you want to give it a default at the end but want that ordering to be changeable (so you can't use the ID. 2. There is a pre-existing key that is used that starts at 0 or something where your primary key can't "line up" with the existing 0-based key. – Dan Hoover Feb 06 '22 at 10:28
2

Had the same problem. There is how i resolved it:

DELIMITER //
CREATE TRIGGER `estimate_before_insert` BEFORE INSERT ON `estimate` FOR EACH ROW BEGIN
DECLARE newNum INT DEFAULT 0;
   SET newNum = (SELECT max(num) FROM estimate) + 1;
   IF newNum IS NULL THEN
    SET newNum = 1;
   END IF;
SET NEW.num = newNum;
END//
DELIMITER ;
  • I am a little confused, wouldn't the primary key (auto increment) always equal this column? I understand this will work, but what is the practical reason for doing something like this? – Jairus Dec 20 '20 at 20:43
  • If You delete last row, and then continue to add other rows, auto_inc will continue numbering as if there are no deleted rows, thus numbering will look like 1; 2; 4; 5; 19; 20; 21 ... With trigger You can make it to continue actual numbering, so there will be no "blank' estimates. In other case may be someone need to add +3 or something. – Ainars Berzins Dec 21 '20 at 21:31
  • So to clarify you are doing it for sequential numbering? Most systems implement a wrapper around fetching rows, pagination for example; – Jairus Dec 21 '20 at 23:47
1

There are plenty of points, all of the people that posted otherwise just have not encountered a problem requiring it yet.... Here let me give an example

You have a customer table that your database users enter new customers into, under that you have some sub tables like address or positions, under those you have further sub tables to hold more specific data. NOW, lets say your users enter the same customer twice on accident and you need to merge all of the sub tables under 1 primary customer record....

Instead of wiping your table, reordering your sub tables or manually moving data over you can instead, link your sub tables to a key field that can be modified (even duplicated if you merge primary keys but thats for another lesson) Then have a second field that does not get modified when needing to merge. This gives you a primary AI key and a second 'changeable' field to tie your sub tables to...

Look up 'Merge linked primary and sub tables in mysql' and see the horrors that it would require a database admin to solve this simple problem..

Dellsmash
  • 21
  • 2
0

My use case was to have to AI columns, one as a PK and another one to shuffle the order of items.

I thought of making a MySQL trigger to initialise the second AI column with the value of the first column so that I can shuffle it later. But turns out the after insert triggert in MySQL did not allow updation

I accomplished it very easily using Sequelize Hooks

You can use something similar to the following if you are working with Sequelize:

db.define('songs', { <your_model_definition> }, {
    hooks: {
        afterCreate: async (item, {}) => {
            //id here is the PK which is Auto Increment (AI)
            //order is the second key I want as AI
            await item.update({ order: item.id}); 
            console.log("afterCreate", item);
        }
    }
})
-1

If you have two auto_increment columns they would be the same, so there is no point having two auto_increment columns.

QuentinB
  • 133
  • 1
  • 7
  • 5
    but I want to add sequence of articles which I want to shuffle later. but the primary key values I cant shuffle – John Apr 02 '14 at 22:46
  • Then have a look there, that might help http://stackoverflow.com/questions/469009/can-you-access-the-auto-increment-value-in-mysql-within-one-statement – QuentinB Apr 02 '14 at 22:52
  • Maybe you just create one auto increment field and one normal int field, do an insert, and then immediately after do an update to set the normal int field of the row you just updated to the auto_increment field? – Andrew Whatever Apr 02 '14 at 22:54
-1

Q: What should I do?

A: Review the reasons you think you need a second AUTO_INCREMENT columns, carefully consider what it is you are trying to achieve.

Come up with an alternate design that doesn't require you to add two AUTO_INCREMENT columns to a MySQL table.

If you do really need to have a second column with "auto increment" type behavior, one way to get that is to add a second dummy table with an auto_increment column, and use a BEFORE INSERT trigger to do an insert into the dummy table, and retrieve the id value that was inserted.

Something like this:

CREATE TABLE course_metadata_31_ai
( i INT UNSIGNED PRIMARY KEY AUTO_INCREMENT
);

DELIMITER $$

CREATE TRIGGER course_metadata_31_bi
BEFORE INSERT ON course_metadata_31
FOR EACH ROW
BEGIN
   DECLARE lii INT;
   IF ( NEW.article_id IS NULL OR NEW.article_id < 1 ) THEN
      -- set article_id to auto_increment from dummy table
      INSERT INTO course_metadata_31_ai (i) VALUES (NULL);
      SELECT LAST_INSERT_ID() INTO lii;
      SET NEW.article_id = lii;
      -- DELETE FROM course_metadata_31_ai WHERE i < lii;
   ELSE
      -- set auto_increment col in dummy table to match a larger article_id
      UPDATE course_metadata_31_ai t
        JOIN ( SELECT MAX(r.i) AS i
                 FROM course_metadata_31_ai r
             ) s
          ON s.i = t.i
         SET t.i = GREATEST(t.i,NEW.article_id);
   END IF;
END;
$$

DELIMITER ;

NOTE

You wouldn't necessarily have to delete rows from the dummy table, you wouldn't have to do it in the trigger, but there's no point in keeping them. You'd probably only really need to keep the row that has the largest auto_increment value, just as a prevention against the AUTO_INCREMENT from inadvertently being set lower with an ALTER TABLE statement.)

The IF ELSE in the trigger body is designed to emulate auto_increment behavior... if a value is supplied for article_id, use that, AND if it's larger than the current max value of auto_increment column in the dummy table, update that row in the dummy table to have the larger value (so the next insert that needs an auto_increment value will get the next higher value).

spencer7593
  • 106,611
  • 15
  • 112
  • 140
-2

in the phpMyAdmin set the column property to AI its a tick box on the table structure. you dont even need to pass the details to the database