5

I'm porting some Postgres SQL to MySQL and am trying to set the starting values of three columns to specific values. The table is as follows:

CREATE TABLE ITEM  (
ORDID               NUMERIC(4) NOT NULL,
ITEMID              NUMERIC(4) NOT NULL,
PRODID              NUMERIC(6),
ACTUALPRICE         NUMERIC(8,2),
QTY                 NUMERIC(8),
ITEMTOT             NUMERIC(8,2),
CONSTRAINT ITEM_FOREIGN_KEY FOREIGN KEY (ORDID) REFERENCES ORD (ORDID),
CONSTRAINT ITEM_PRIMARY_KEY PRIMARY KEY (ORDID,ITEMID));

The code I'm trying to port is as follows:

CREATE SEQUENCE ORDID
INCREMENT BY 1
START WITH 622
;

CREATE SEQUENCE PRODID
INCREMENT BY 1
START WITH 200381
;

CREATE SEQUENCE CUSTID
INCREMENT BY 1
START WITH 109
;

However, when trying to run this I'm getting the error:

SQL query:

CREATE SEQUENCE ORDIDINCREMENT BY 1 START WITH 622 ;


MySQL said: Documentation

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SEQUENCE ORDID
INCREMENT BY 1
START WITH 622' at line 1 

I know that there is no direct equivalent to a SEQUENCE in MySQL but I can't figure out a reasonable way to achieve the same thing without it. Any ideas?

3 Answers 3

4

You can use table with AUTO_INCREMENT key to emulate sequences:

CREATE TABLE ORDID (id INT PRIMARY KEY AUTO_INCREMENT) AUTO_INCREMENT = 622;
CREATE TABLE PRODID (id INT PRIMARY KEY AUTO_INCREMENT) AUTO_INCREMENT = 200381;
CREATE TABLE CUSTID (id INT PRIMARY KEY AUTO_INCREMENT) AUTO_INCREMENT = 109;

Each of the table represents a 'sequence'. To use one in your CREATE TABLE:

CREATE TABLE ITEM  (
ORDID               INT NOT NULL,
ITEMID              NUMERIC(4) NOT NULL,
PRODID              NUMERIC(6),
ACTUALPRICE         NUMERIC(8,2),
QTY                 NUMERIC(8),
ITEMTOT             NUMERIC(8,2),
CONSTRAINT ITEM_FOREIGN_KEY FOREIGN KEY (ORDID) REFERENCES ORDID (ID),
CONSTRAINT ITEM_PRIMARY_KEY PRIMARY KEY (ORDID,ITEMID));

You can then use INSERT to get a new value from your 'sequence':

INSERT INTO ordid VALUES (null);
SELECT LAST_INSERT_ID();
3
  • Thanks for the reply. Not quite sure why you're using CREATE TABLE in the first example? I.e. CREATE TABLE ORDID (id INT...) What is the relevance of creating tables for the items that are supposed to be columns in my ITEM table? Commented Nov 9, 2015 at 19:56
  • 1
    First three table are your 'sequences'. MySQL doesn't support sequences, but closest idiom is to use table with single AUTO_INCREMENT column. Commented Nov 9, 2015 at 19:57
  • 1
    The emulated "sequences" will require additional queries. For every row you want to insert you must first insert into the appropriate sequence table and use LAST_INSERT_ID for the primary key. If you can use AUTO_INCREMENT instead your database will be far easier to work with. Commented Nov 9, 2015 at 20:21
3

MySQL uses AUTO_INCREMENT for that purpose. Rather than making new sequence types, you apply it to an existing integer column.

Unfortunately you can only have one per table.

There can be only one AUTO_INCREMENT column per table, it must be indexed, and it cannot have a DEFAULT value.

And they must be integers, numeric doesn't work. This will probably improve your schema as 9999 orders and items seems very small.

AUTO_INCREMENT applies only to integer and floating-point types.

And if that wasn't enough, you can't have an AUTO_INCREMENT on a multi-key primary key. Only the vastly inferior MyISAM table format allows that.

So you cannot easily translate your PostgreSQL tables to MySQL verbatim.

You sure you want to convert to MySQL?


In your case, item.ordid is a reference so it will be incremented in its own table. item.prodid is probably also a reference and somebody forgot to declare it that. This leaves just item.itemid to be declared AUTO_INCREMENT, but it's part of the primary key. It probably doesn't need to be, it can just be unique.

In fact, the ITEM table seems more like it's tracking orders of products, not items... but then there's also a product ID? I don't know what an "item" is.

You wind up with something like this:

CREATE TABLE ITEM (
       ITEMID              INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
       PRODID              INTEGER REFERENCES PROD(PRODID),
       ORDID               INTEGER NOT NULL REFERENCES ORD (ORDID),
       ACTUALPRICE         NUMERIC(8,2),
       QTY                 NUMERIC(8),
       ITEMTOT             NUMERIC(8,2),

       UNIQUE(ORDID, ITEMID)
)

CREATE TABLE ORD (
       ORDID               INTEGER PRIMARY KEY AUTO_INCREMENT,
       ...
) AUTO_INCREMENT = 622;

CREATE TABLE PROD (
       PRODID              INTEGER PRIMARY KEY AUTO_INCREMENT,
       ...
) AUTO_INCREMENT = 200381;

You can also set the AUTO_INCREMENT starting point after the fact with ALTER TABLE. Because it's a table attribute, not a column attribute, it happens on the table itself.

ALTER TABLE CUST AUTO_INCREMENT=109;

It's largely unnecessary to set the AUTO_INCREMENT starting point if you're importing an existing data set. AUTO_INCREMENT will always use MAX(column) and it cannot be set lower than this. It doesn't matter what you start it at if the table is already populated.

1
  • Thanks for this! It didn't directly answer the question as other answers did but it gave me a lot of insight to understand what was going on and helped me realise that I was going about the issue the wrong way entirely and thus my question was somewhat misleading. Commented Nov 10, 2015 at 5:53
3

You can create a table with an AUTO_INCREMENT field and set its initial value.

 create table myseq(
   my_id   int auto_increment primary key
 ) auto_increment=100;

Or use ALTER TABLE to reset the value whenever you want:

 alter table myseq auto_increment = 100;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.