How can we migrate sequence in PostgreSQL to Mysql - mysql

All,
I am trying to migrate from PostgreSQL DB to MySql DB. I have used sequence in some table to get auto increment column other than the primary key. How to create auto increment column which is the primary key in Mysql DB.
I am listing an example table below in PostgreSQL.
CREATE TABLE bills
(
id serial NOT NULL,
billname character varying(255) NOT NULL,
invoiceid character varying(255) NOT NULL DEFAULT nextval('bill_invoiceid_seq'::regclass),
CONSTRAINT combine_campaigns_pkey PRIMARY KEY (id)
)
In the example, "id" is the primary key and invoice id is not a key but getting auto increment

MySQL int auto_increment primary key should be very similar to postgreSQL serial (which does not need to be a primary key)
If you want to reserve some used sequence, you can insert a value (eg 3000) into MySQL auto_increment field, after that any new record will increase from this value i.e. 3001 onwards:

The equivalent for a SERIAL column in mysql is AUTO_INCREMENT. Define your primary key as follows:
CREATE TABLE my_table(
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
...
)
or
CREATE TABLE my_table(
id int NOT NULL AUTO_INCREMENT ,
...
PRIMARY KEY(id)
)
Be aware that in mysql you can only have one AUTO_INCREMENT per table. Also worth mentioning is that you are moving from an RDBS that is rich in features and closer to standard compliance to one that has less features and less compliant.

Related

Differences between defining primary key - along with column name, at the end of create table stmt, adding primary key index after create table stmt

There are three ways I have seen to define primary keys.
Define along with its column name definition:
CREATE TABLE test (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-- other fields
);
Define the key at the end of the table definition:
CREATE TABLE test (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
-- other fields
PRIMARY KEY (id)
);
Adding primary key index after table creation. Generally I have seen this in phpMyAdmin's exported .sql files. (Does it depends on the storage engine used?)
CREATE TABLE test (
id INT UNSIGNED NOT NULL,
-- other fields
);
ALTER TABLE test
ADD PRIMARY KEY (id),
MODIFY id INT UNSIGNED NOT NULL AUTO_INCREMENT;
What are the internal differences between all these methods?
Mostly I have seen that importing an SQL file having the 3rd method takes longer time than having other methods.
Edit (After Bill Karwin told that "(the) example(s) shows no import of data"):
The examples above don't contain INSERT queries, but what differences there will be if there are INSERT statements after each of these CREATE TABLE queries for inserting data in them?
There is no difference between the first two forms. It's only a syntax convenience if your primary key is a single column. But if you have a multi-column primary key, you must define the PK as a table constraint:
CREATE TABLE test (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
other INT NOT NULL,
-- other fields
PRIMARY KEY (id, other)
);
The third form is almost the same, because you define the primary key before inserting any data into the table. The only effect is that metadata is altered by the second DDL statement.
Some people claim that adding the primary key after importing data is faster, but this is not true for MySQL's default storage engine InnoDB. The table data is stored as a clustered index. If you don't declare your own primary key, another row id is created implicitly, and this becomes the key for the clustered index. So you're inserting into an index one way or the other.
It's possible that in the old MyISAM storage engine, inserting data to a table with no primary key is a little faster. But you have to count the extra time it takes to add the primary key after you're done inserting data.
In any case, your example shows no import of data, so it's moot.

external GUID to satisfy unique constraint in mysql

I have a MYSQL 8.x table, each row is unique since the PK is auto incremented. A column transactionID is used to store an external transactionID that needs to be coupled with the row/record.
However a new requirement came and we want to create a new row with the same transactionID. I was thinking to add a new column that holds the GUID of the transaction.
Is this good idea? Is this going to be slow? Are there any second thougths regarding uuid as strings? MySQL 8.0 added UUID_TO_BIN and BIN_TO_UUID function that could store UUID as number.
CREATE TABLE `testme`.`new_table` (
`ID` INT NOT NULL AUTO_INCREMENT,
`transactionID` INT NOT NULL,
`maybe_uuid` VARCHAR(45) NOT NULL,
PRIMARY KEY (`ID`));
ALTER TABLE `testme`.`new_table`
ADD UNIQUE INDEX `index2` (`transactionID` ASC, `maybe_uuid` ASC) VISIBLE;
;
GUIDs are not great for use as a primary key for many reasons that i will not detail here and it would faster to use you auto_increment key that is already in place. But if you also need to store the GUID it is perfectly reasonable to just add another column for that. And you can use the two functions you mentioned.

Postgres Sequence Port to MySQL

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?
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.
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;
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();

What is the default primary key generation strategy for MySQL

I have been using AUTO_INCREMENT attribute to generate a primary key when a new row is inserted into a table in MySQL.
Could somebody help me understand what is the default primary key generation strategy for MySQL and how does it work?
EDIT
Hibernate has a identifier generation strategy native selects identity, sequence or hilo depending upon the capabilities of the underlying database. I used MySQL with hibernate.hbm2ddl.auto=update which generated id BIGINT(20) NOT NULL AUTO_INCREMENT for id property of Long Java data type.
I am trying to understand how did Hibernate choose AUTO_INCREMENT when it used SchemaExport tool. Is AUTO_INCREMENT the default primary key generation strategy for MySQL?
From here
The AUTO_INCREMENT attribute can be used to generate a unique identity for new rows.
If no value was specified for the AUTO_INCREMENT column, so MySQL assigned sequence numbers automatically. You can also explicitly assign 0 to the column to generate sequence numbers. If the column is declared NOT NULL, it is also possible to assign NULL to the column to generate sequence numbers.
The value will be incremented for each new row
The value is unique, duplicates are not possible
If a row is deleted, the auto_increment column of that row will not be re-assigned.
The auto_increment value of the last inserted row can be accessed using the mySQL function LAST_INSERT_ID() but it must be called right after the insert query, in the same database connection
Always not necessary to use auto increment to put it as primary key.
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
PRIMARY KEY (P_Id)
)
You can use 'SERIAL' data type.
CREATE TABLE test(
"id" Serial NOT NULL,
);
ALTER TABLE "test" ADD CONSTRAINT "Key1" PRIMARY KEY ("id");

How can we create primary key as a decimal data type, and can it be auto increment

in my database we have a field which is going beyond int max value,
i can choose bigint for primary key but i am wondering can we use decimal(2,18) for primary key and if we can than how we auto increment this field ?
You may have a decimal as a primary key, but it must have a scale of 0.
SQL Server will handle the auto-incrementing.
Example:
CREATE TABLE my_table (
id decimal(18,0) identity primary key,
some_column varchar(200)
);
Reference: http://beyondrelational.com/modules/2/blogs/28/posts/10331/sql-server-what-are-the-data-types-supported-in-identity-columns.aspx
See your master plan in action here: http://sqlfiddle.com/#!3/e491d/1/0