MySQL alter table partitioning syntax - mysql

I tried to do table partitioning in MySQL by altering the table with the following code:
ALTER TABLE tt DROP PRIMARY KEY, ADD PRIMARY KEY(id, st);
ALTER TABLE tt ADD PARTITION BY LIST(st) (
PARTITION p0 VALUES IN (20,10),
PARTITION p1 VALUES IN (0,-10)
);
but got the following error:
Mysql::Error: 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 'ALTER TABLE tt ADD PARTITION (PARTITION p0 VALUES IN' at line 2:
Can someone please let me what's wrong with the syntax?

ALTER TABLE orders PARTITION BY LIST(st) (
PARTITION p0 VALUES IN (20,10),
PARTITION p1 VALUES IN (0,-10)
);
The ADD is extraneous - the syntax is essentially identical to the CREATE TABLE statement.
Make sure you have a good, restorable backup before doing this.
Log:
mysql> create table orders (id int, st int, whatever varchar(10), primary key (id));
Query OK, 0 rows affected (0.06 sec)
mysql> ALTER TABLE orders DROP PRIMARY KEY, ADD PRIMARY KEY(id, st);
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE orders PARTITION BY LIST(st) (
-> PARTITION p0 VALUES IN (20,10),
-> PARTITION p1 VALUES IN (0,-10)
-> );
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0

Related

mysql "create table if not exists", determine if table created

Is it possible to determine if a table was created or already existed when using create table if not exists...?
There seem to be two variables returned:
(query ok, affected_rows)
The query always returns (1, 0) regardless of if the table was created or already existed.
But it seems a create schema if not exists does return affected_rows=1.
Thanks.
I get 1 warning if the table exists (mysql 8.0.25):
mysql> CREATE TABLE IF NOT EXISTS `test` (`id` INT NOT NULL, PRIMARY KEY (`id`));
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE IF NOT EXISTS `test` (`id` INT NOT NULL, PRIMARY KEY (`id`));
Query OK, 0 rows affected, 1 warning (0.00 sec)
The warning is 1050 Table 'test' already exists
But you can just check if the table exists before creating it

MySQL : Load Data Infile with AI PRIMARY Key and On Duplicate Key Update

I find a correct solution how Load Data Infile in MySQL can work with On Duplicate Key Update. Here is the code I use (get it from stack overflow):
CREATE TEMPORARY TABLE temporary_table LIKE employee_table;
SHOW INDEX FROM temporary_table;
DROP INDEX `PRIMARY` ON temporary_table;
LOAD DATA INFILE 'csv/employee_table'
INTO TABLE temporary_table FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'
(
`AutoID`, `Name`, `Age`, `Salary`
)
SHOW COLUMNS FROM employee_table;
INSERT INTO employee_table
SELECT * FROM temporary_table
ON DUPLICATE KEY UPDATE AutoID = Values(AutoID);
DROP TEMPORARY TABLE temporary_table;
This code above is working properly to update the table with new records that have different ID only. However, when the PRIMARY key is auto increment (AI), it fails to work. It shows that this below code cannot be run on auto increment PRIMARY key.
DROP INDEX `PRIMARY` ON temporary_table
Here is the error message:
#1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
I am confused since if I don't use the auto increment, it run perfectly. Anyone know how to fix this problem? Thanks in advance.
there is two procedure.
1) your problem solution.
mysql> DROP INDEX `PRIMARY` ON test5;
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
mysql> show create table test5;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test5 | CREATE TEMPORARY TABLE `test5` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`address` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> alter table test5 modify `id` int(11) NOT NULL;
Query OK, 0 rows affected (0.21 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
mysql> DROP INDEX `PRIMARY` ON test5;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
mysql> show create table test5;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test5 | CREATE TEMPORARY TABLE `test5` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`address` varchar(100) DEFAULT NULL,
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
2) Best Solution..
we can replace first (two steps) with below single query in the procedure.
1) and 2) we can create new table with same reference structure and without any indexes.
CREATE TEMPORARY TABLE temporary_table SELECT * FROM target_table WHERE 1=0;
Instead of..
1) Create a new temporary table.
CREATE TEMPORARY TABLE temporary_table LIKE target_table;
2) Optionally, drop all indices from the temporary table to speed things up.
SHOW INDEX FROM temporary_table; DROP INDEX PRIMARY ON temporary_table; DROP INDEX some_other_index ON temporary_table;
you can also refer below link.
MySQL LOAD DATA INFILE with ON DUPLICATE KEY UPDATE

MySql - doesn't support BLOB/TEXT columns

create temporary table if not exists tmp engine=memory
SELECT id, CONCAT(TRIM(lastName),TRIM(firstName),TRIM(zip)) AS identify
FROM customers
GROUP BY identify;
While running the procedure I get the following error message:
The used table type doesn't support BLOB/TEXT columns
I already saw this thread but it didn't help me.
The types on the columns are the following:
lastName -> VARCHAR(255)
firstName -> VARCHAR(255)
zip -> VARCHAR(10)
when I exclude the zip from the procedure it works as It should so I guess there is a problem with the length of the varchar?
Does anyone knew a solution without changing the varchar length of zip from 10 to 255?
Incidence is presented by the value of the constant CONVERT_IF_BIGGER_TO_BLOB:
/**
CHAR and VARCHAR fields longer than this number of characters are converted
to BLOB.
Non-character fields longer than this number of bytes are converted to BLOB.
Comparisons should be '>' or '<='.
*/
#define CONVERT_IF_BIGGER_TO_BLOB 512 /* Used for CREATE ... SELECT */
mysql-server/sql/sql_const.h::52
and
16.3 The MEMORY Storage Engine
...
Support for variable-length data types (including BLOB and TEXT) not supported by MEMORY.
Example:
mysql> DROP TEMPORARY TABLE IF EXISTS `tmp`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TEMPORARY TABLE IF NOT EXISTS `tmp` ENGINE=MEMORY
-> SELECT SPACE(512) `tmp_col`;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> DROP TEMPORARY TABLE IF EXISTS `tmp`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TEMPORARY TABLE IF NOT EXISTS `tmp` ENGINE=MEMORY
-> SELECT SPACE(513) `tmp_col`;
ERROR 1163 (42000): The used table type doesn't support BLOB/TEXT columns
Try:
mysql> DROP TABLE IF EXISTS `tmp`, `customers`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `customers` (
-> `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> `lastName` VARCHAR(255) NOT NULL,
-> `firstName` VARCHAR(255) NOT NULL,
-> `zip` VARCHAR(10) NOT NULL
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TEMPORARY TABLE IF NOT EXISTS `tmp` (
-> `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY,
-> `identify` VARCHAR(520) NOT NULL
-> ) ENGINE=MEMORY;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `tmp`
-> SELECT `id`, CONCAT(TRIM(`lastName`),
-> TRIM(`firstName`),
-> TRIM(`zip`)) `identify`
-> FROM `customers`
-> GROUP BY `id`, `identify`;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
My experience with ENGINE=MEMORY was that the charset is also relevant.
varchar(65000) with charset latin1 worked; charset UTF8 did not
ENGINE=MEMORY DEFAULT CHARSET=latin1

Set AUTO_INCREMENT on a column with missing values

I have a table called users in my database. It has a field id of type int. As of now this is manually incremented for every user that registers and some intermediate values are missing because of deleted user accounts. I cannot change the user id of other registered users . I tried to change this column to AUTO_INCREMENT using this statement
ALTER TABLE `userinfo` CHANGE `id` `id` BIGINT(20) NOT NULL AUTO_INCREMENT;
But I got the following error
1062 - ALTER TABLE causes auto_increment resequencing, resulting in
duplicate entry '1' for key 'PRIMARY'
I only have around 200 users in my table. So I wanted to start AUTO_INCREMENT from 201. I executed the following statements
ALTER TABLE `userinfo` AUTO_INCREMENT=201;
ALTER TABLE `userinfo` CHANGE `id` `id` INT(10) NOT NULL AUTO_INCREMENT;
But still I encounter the same issue.
If you don't have duplicates (id), you should not have problems:
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.17 |
+-----------+
1 row in set (0.00 sec)
mysql> DROP TABLE IF EXISTS `userinfo`;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE IF NOT EXISTS `userinfo` (
-> `id` INT(11) NOT NULL
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `userinfo`
-> (`id`)
-> VALUES
-> (1),
-> (2),
-> (3),
-> -- (1),
-> (10),
-> (11),
-> (15),
-> (20),
-> (182),
-> (191);
Query OK, 9 rows affected (0.00 sec)
Records: 9 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE `userinfo`
-> CHANGE `id` `id` BIGINT(20) NOT NULL
-> PRIMARY KEY AUTO_INCREMENT;
Query OK, 9 rows affected (0.00 sec)
Records: 9 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE `userinfo` AUTO_INCREMENT = 201;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SHOW CREATE TABLE `userinfo`\G
*************************** 1. row ***************************
Table: userinfo
Create Table: CREATE TABLE `userinfo` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
In another case:
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.17 |
+-----------+
1 row in set (0.00 sec)
mysql> DROP TABLE IF EXISTS `userinfo`;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE IF NOT EXISTS `userinfo` (
-> `id` INT(11) NOT NULL
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `userinfo`
-> (`id`)
-> VALUES
-> (1),
-> (2),
-> (3),
-> (1), -- Duplicate
-> (10),
-> (11),
-> (15),
-> (20),
-> (182),
-> (191);
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE `userinfo`
-> CHANGE `id` `id` BIGINT(20) NOT NULL
-> PRIMARY KEY AUTO_INCREMENT;
ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
Try resetting the column to primary key, like this:
ALTER TABLE `userinfo` CHANGE `id` `id` INT(10) PRIMARY KEY AUTO_INCREMENT;
You can just drop auto_increment then set auto_increment, do not need recreate primary key
ALTER TABLE `userinfo` CHANGE `id` `id` int NOT NULL;
ALTER TABLE `userinfo` AUTO_INCREMENT=9;
ALTER TABLE `userinfo` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT;
I was having this same problem/error (MySql 5.7.28) with bulk inserts of data that was missing primary key/auto_increment values - even though there were no duplicates. I wanted to preserve the primary key and needed to preserve the original field values also as resequencing would have caused data-integrity problems in the system.
My solution was to remove the auto_increment and then primary key as suggested above:
ALTER TABLE `userinfo` CHANGE `id` `id` int NOT NULL;
ALTER TABLE `userinfo` DROP PRIMARY KEY;
Then run my bulk insert statement without resequencing problems.
Then restore the primary key and original values using the following steps:
renaming the original PK/auto-increment field which now has the desired values in it
creating a new PK/auto-increment field with the original field name
setting the auto-increment value to one more than the max value of the renamed field
copying the original values into the new PK/auto-increment field
dropping the renamed field (now you have the original schema with PK/auto-increment field with original gaps in the sequence as desired.
Here is the sql for the first two steps:
ALTER TABLE `userinfo` CHANGE `id` `orig_id` INT;
ALTER TAble `userinfo` add id int auto_increment not null primary key;
Then use the following query result:
select max(orig_id) + 1 from `userinfo`;
to set the new auto-increment, before updating the new PK/auto-increment values:
ALTER TABLE `userinfo` AUTO_INCREMENT=201;
UPDATE `userinfo` set id = orig_id;
ALTER TABLE `userinfo` drop column orig_id;
and now I've got the original table values copied exactly as wanted. I hope this helps others save time.

How to use ALTER TABLE in MySQL on a column named partition

I have a MySQL table with a column named partition. As it's a reserved keyword, I should be able to use backticks to use it in queries. It works with SELECT, but not with ALTER TABLE.
If I try :
ALTER TABLE `table` DROP `partition`;
or
ALTER TABLE `table` CHANGE `partition` `othername` INT;
MySQL complains with the same error :
Error code 1054: Unknown column 'partition' in 'partition function'
I tried in 'terminal', via MySQL Workbench or through Java JDBC, I always get the same error.
Any suggestion to get rid of that column (without losing / re-creating the whole table ...) ?
EDIT:
You can test it with a small table like that :
CREATE TABLE `testpart` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `partition` smallint(6) NOT NULL, UNIQUE KEY `id` (`id`,`partition`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY HASH(partition) PARTITIONS 16;
Then try
ALTER TABLE `testpart` DROP COLUMN `partition`;
the first try is nearly correct, but you must say what to drop COLUMN. try this to delete them. Backticks are also working.
ALTER TABLE `table` DROP COLUMN `partition`;
here is the Manual page from Mariadb : https://mariadb.com/kb/en/mariadb/alter-table/
sample
i must add some infos to my answer:
the table has PARTITION
and the COLUMN that you want to change / remove is the KEY therefore
you must first remove the PARTITION before you can change them
the name of the COLUMN is a KEYWORD, so you must always quote it with backticks
create a table with 16 partitions
MariaDB [yourschema]> CREATE TABLE testpart (
-> id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-> `PARTITION` SMALLINT(6) NOT NULL,
-> UNIQUE KEY id (id,`PARTITION`)
-> ) ENGINE=MyISAM DEFAULT CHARSET=latin1
-> PARTITION BY HASH (`PARTITION`)
-> PARTITIONS 16 ;
Query OK, 0 rows affected (0.12 sec)
now remove the paritions
MariaDB [yourschema]> ALTER TABLE `testpart` REMOVE PARTITIONING;
Query OK, 0 rows affected (0.35 sec)
Records: 0 Duplicates: 0 Warnings: 0
remove the (or change) the COLUMN
MariaDB [yourschema]> ALTER TABLE `testpart` DROP COLUMN `PARTITION`;
Query OK, 0 rows affected (0.21 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [yourschema]>
Does partition column have int values?
Try changing that accordly.