MySQL adding (num) to smallint column - mysql

When I create a table in MySQL specifying smallint as a column, but then use show create table or even mysqldump, MySQL has added (5) after the smallint definition, as below.
I'm guessing it doesn't really matter as far as the data is concerned, but can anyone explain why and if/how I can stop it doing this?
As an aside, I am attempting to change an existing database table to exactly match that of a new sql script. I could always alter the new sql script, but I'd prefer to alter the existing table if possible (think software install versus software upgrade).
DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`status` varchar(100) NOT NULL DEFAULT '',
`port` smallint unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SHOW CREATE TABLE test;
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`status` varchar(100) NOT NULL DEFAULT '',
`port` smallint(5) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

No, you can't stop the SHOW CREATE TABLE from including the display width attribute for integer types.
If a value for the display width is not included in the column declaration of an integer type, MySQL supplies a default value for it. A value of 5 is the default value for SMALLINT UNSIGNED.
The display width doesn't have any affect on the values that can be stored or retrieved. Client applications can make use of the value for formatting a resultset.
Reference: http://dev.mysql.com/doc/refman/5.6/en/numeric-type-attributes.html

tMySQL is simply setting the (displayed) length of the column to match he data type (max value 65535, five digits). To change this, you can write:
port smallint (3) unsigned NOT NULL DEFAULT '0',
if you like.

Try this start adding values in your table.
<mysql> CREATE TABLE test(
-> ID SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> Name VARCHAR(100) NOT NULL
-> );>

Related

MySql: AUTO_INCREMENT is missing from tables

MySql: AUTO_INCREMENT is missing from some tables after running for about one month.
Initially: (show create table Foo)
CREATE TABLE `Foo` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
`type` tinyint(2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8
After one month:
CREATE TABLE `Foo` (
`id` bigint(20) NOT NULL,
`name` varchar(10) NOT NULL,
`type` tinyint(2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
AUTO_INCREMENT is missing. What is the cause?
Mysql Server version: 5.6.25, Linux
Someone must have changed it. This change does not happen spontaneously.
I can reproduce this change myself:
CREATE TABLE Foo ( id BIGINT AUTO_INCREMENT, ...
ALTER TABLE Foo MODIFY COLUMN id BIGINT;
SHOW CREATE TABLE Foo\G
*************************** 1. row ***************************
Table: foo
Create Table: CREATE TABLE `foo` (
`id` bigint(20) NOT NULL,
`name` varchar(10) NOT NULL,
`type` tinyint(2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Now the column shows it is BIGINT but not AUTO_INCREMENT.
Every time you MODIFY COLUMN or CHANGE COLUMN, you must repeat all the column options like NOT NULL and AUTO_INCREMENT and DEFAULT, or else it will revert to defaults (i.e. not auto-increment).
So I would interpret this shows that someone did an ALTER TABLE and didn't remember to include the AUTO_INCREMENT column option.
Just a thought.
If you have binary logs, you may see the alter query on the logs and when it was run. :)
Check if the binary log is enabled by
show variable like 'log_bin';
If binary log is enabled, find the likely period that the query could have been executed and then use mysqlbinlog to help you find it.
If binary log is not enabled, bad luck - as the previous post by Bill Karwin has suggested mysql does not change it on its own - someone must have changed it.

how do I get the field 'aaj' updated with change of date in the following table?

CREATE TABLE `aaj` (
`ID` int(10) NOT NULL,
`aaj` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`mahina` varchar(6) GENERATED ALWAYS AS (convert(date_format(`aaj`,'%y/%m') using utf8mb4)) STORED NOT NULL,
`saptaah` varchar(7) GENERATED ALWAYS AS (convert(date_format(`aaj`,'%x/%v') using utf8mb4)) STORED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I think that you want ON UPDATE CURRENT_TIMESTAMP:
CREATE TABLE `aaj` (
`ID` int(10) NOT NULL,
`aaj` timestamp NOT NULL
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
`mahina` varchar(6) GENERATED ALWAYS
AS (convert(date_format(`aaj`,'%y/%m') using utf8mb4)) STORED NOT NULL,
`saptaah` varchar(7) GENERATED ALWAYS
AS (convert(date_format(`aaj`,'%x/%v') using utf8mb4)) STORED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Side note: it is usually not a good practice to have a column with the same name as the table (here, aaj): from database perspective this is not a problem, but it tends to make things confusing for human beings.

Safely alter a column in MySQL 5.5

I have found myself looking after an old testlink installation, all the people responsible have left and it is years since I did any serious SQL work.
The underlying database is version 5.5.24-0ubuntu0.12.04.1
I do not have all the passwords, but I have enough rights to do a backup without locks;
mysqldump --all-databases --single-transaction -u testlink -p --result-file=dump2.sql
I really do not want to a attempt to restore the data!
We need to increase the length of the name field in testlink, various pages lead me to increasing the length of a field in the nodes_hierarchy table.
The backup yielded this;
CREATE TABLE `nodes_hierarchy` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`parent_id` int(10) unsigned DEFAULT NULL,
`node_type_id` int(10) unsigned NOT NULL DEFAULT '1',
`node_order` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `pid_m_nodeorder` (`parent_id`,`node_order`)
) ENGINE=MyISAM AUTO_INCREMENT=184284 DEFAULT CHARSET=utf8;
I have only really one chance to get this right and cannot lose any data. Does this look exactly right?
ALTER TABLE nodes_hierarchy MODIFY name VARCHAR(150) DEFAULT NULL;
That is the correct syntax.
Backup
You should backup the database regardless how safe this operation is. It seems like you are already planning on it. It is unlikely you will have problems. Backup is just an insurance policy to account for unlikely occurrences.
Test table
You seem to have ~200K records. I'd recommend you make a copy of this table by just doing:
CREATE TABLE `test_nodes_hierarchy` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`parent_id` int(10) unsigned DEFAULT NULL,
`node_type_id` int(10) unsigned NOT NULL DEFAULT '1',
`node_order` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `test_pid_m_nodeorder` (`parent_id`,`node_order`)
) ENGINE=MyISAM AUTO_INCREMENT=184284 DEFAULT CHARSET=utf8;
Populate test table
Populate the test table with:
insert into test_nodes_hierarchy
select *
from nodes_hierarchy;
Run alter state on this test table
Find how long the alter statement will take on the test table.
ALTER TABLE test_nodes_hierarchy
MODIFY name VARCHAR(150) DEFAULT NULL;
Rename test table
Practice renaming the test table using:
RENAME TABLE test_nodes_hierarchy TO test2_nodes_hierarchy;
Once you know the time it takes, you know what to expect on the main table. If something goes awry, you can replace the drop the nodes_hierarchy table and just rename test_nodes_hierarchy table.
That'll just build confidence around the operation.

How to create table in MariaDB?

When I try to create simple table via HeidiSQL I'm getting an error like this
CREATE TABLE `prg_config` (
`id` INT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NULL DEFAULT '',
`value` VARCHAR NULL DEFAULT ''
) COLLATE='utf8_bin';
Please Check Following query :
CREATE TABLE prg_config (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NULL DEFAULT '',
`value` VARCHAR(50) NULL DEFAULT '',
PRIMARY KEY (id)
)COLLATE='utf8_bin';
CREATE TABLE `prg_config` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(50) NULL DEFAULT '',
`value` VARCHAR(100) NULL DEFAULT ''
) COLLATE='utf8_bin';
Add PRIMARY KEY/UNIQUE/KEY to AUTO_INCREMENT column
Specify length for VARCHAR.
AUTO_INCREMENT :
Each table can have only one AUTO_INCREMENT column. It must defined as
a key (not necessarily the PRIMARY KEY or UNIQUE key). If the key
consists of multiple columns, the AUTO_INCREMENT column must be the
first one, unless the storage engine is Aria or MyISAM.
SqlFiddleDemo
If you created that table with HeidiSQL's table designer, I guess it looked like this:
HeidiSQL does not complain when you make the length/set empty for a VARCHAR column. MySQL + MariaDB both require a length for VARCHAR columns, so I can probably fix that by not letting the user to make the VARCHAR length empty.

Is a master table with only one column necessary in this mysql example?

I have a mysql DB with a table that holds version information for multiple other tables. In order to link to the same family of versions I have a version_master table that holds a primary key to the family of versions that the link refers to. I was wondering if there was a more elegant solution without the need for a version_master table.
CREATE TABLE IF NOT EXISTS `version` (
`version_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`version_master_id` int(10) unsigned NOT NULL,
`major` int(10) unsigned NOT NULL DEFAULT '0',
`minor` int(10) unsigned NOT NULL DEFAULT '0',
`patch` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`version_id`));
CREATE TABLE IF NOT EXISTS `version_master` (
`version_master_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE IF NOT EXISTS `needs_versions` (
`needs_versions_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`name` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`description` text COLLATE utf8_unicode_ci NOT NULL,
`version_master_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`needs_versions_id`));
In this example you can certainly eliminate the version_master table and use the combination of version_id and version_master_id fields as an index. I think you can just drop it, because nothing seem to refer to it with a foreign key.
However, having version_master would be a good idea if you had additional information associated with each family of versions.
Also, you are trying to make a primary key out of the undefined column offer_type_id. It is not clear whether you can logically merge needs_versions with version_master or not. The name itself is not very descriptive. I would recommend not to use verbs in table names.
The other common way to do this is to use SEQUENCEs.
But MySQL does not seem to support them, at least the MySQL manual contains a section on how to simulate sequences using a one row, one column table:
Create a table to hold the sequence
counter and initialize it:
CREATE TABLE sequence (id INT NOT NULL);
INSERT INTO sequence VALUES (0);
Use the table to generate sequence
numbers like this:
UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SELECT LAST_INSERT_ID();