Looking at integer values. It seems that setting the Unsigned attribute overrides the field length.
Traditionally, MYSQL translates the BOOLEAN alias to TINYINT(1).
According to the inter-webs, as of MySQL 8.0.17, display width specifications for integer data types have been deprecated. There are two exceptions to this which include: TINYINT(1)
However, there is a bug (known or unknown IDK) where when I set UNSIGNED on any TINYINT value, the display length is dropped.
Steps to reproduce:
Create a table with a field intended to be used as a BOOLEAN;
CREATE TABLE users (
id int unsigned NOT NULL AUTO_INCREMENT ,
user_name varchar(50) NOT NULL,
password varchar(255) NOT NULL,
is_active tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (id),
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
Observe that the display length on TINYINT(1) is in fact set.
Alter the table to make is_active an UNSIGNED value:
ALTER TABLE users
CHANGE COLUMN is_active is_active TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' ;
Observe that TINYINT no longer has a display length.
List item
Expected result:
I argue that the correct field attribute for a "BOOLEAN" would be unsigned since your options would be 0 or 1. Not negatives. Therefore I would expect that the UNSIGNED behavior for TINYINT(1) be identical to the signed behavior, and field display length would be set / retained.
Question:
Has anyone else encountered this behavior? Any ideas on a work around? Right now I am sticking with signed tinyint's...
Related
I am using MYSQL as database. Check is this table definition
CREATE TABLE `test`.`header`
(
`header_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(500) NOT NULL,
`body` VARCHAR(5000) NOT NULL,
`created_by_id_ref` BIGINT UNSIGNED NOT NULL,
`created_date` DATETIME NOT NULL,
`updated_date` DATETIME NULL DEFAULT NULL,
`is_void` TINYINT(1) NULL DEFAULT NULL,
PRIMARY KEY (header_id`) ) ENGINE=INNODB CHARSET=latin1 COLLATE=latin1_swedish_ci;
In my interface user can delete any of the record by simply selecting the record from a grid view. So in that case I am simply updating the "is_void" status to true.
I declared that column by this syntax. which shows above. Here it again.
`is_void` TINYINT(1) NULL DEFAULT NULL,
So If I add an index to this column is this column declaration is good?
In that case records default have null values. For voided records it will be "1".
So if I am going to filter any of those records for voided records I have to use
Select ........ where is_void=1;
If I want to filter non voided records I can use
Select ........ where is_void IS NULL;
So is this NULL declaration affect to my select query performance? (Remember I indexed this column)
Or Shall I declare my column as
`is_void` TINYINT(1) NOT NULL,
and then I have insert "0" for non voided records. Then if I want to filter non voided records I can use
Select ........ where is_void=0;
So What is the best?
where is_void=0; or where is_void IS NULL;
Thank you very much.
In terms of performances, both approaches are equivalent*.
In terms of logic, NULL is widely regarded as meaning "unknown value" or "not applicable". Go with 1 or 0, as defined by the TRUE and FALSE constants.
Also, even though MySQL implements it as an alias for TINYINT(1), I would advise using the ANSI-standard BOOLEAN type.
* Ok, this is not entirely true in theory.
Following SQL table definition is illustrated one of create table statement from my MYSQL database which is developed by a former developer of my company.
DROP TABLE IF EXISTS `classifieds`.`category_vehicles`;
CREATE TABLE `classifieds`.`category_vehicles`(
`adv_id_ref` BIGINT UNSIGNED NOT NULL,
`category_id_ref` TINYINT UNSIGNED NOT NULL,
`forsale_status` TINYINT (1) NOT NULL,
`vehicle_type_id_ref` TINYINT UNSIGNED NOT NULL,
`price` DOUBLE NULL DEFAULT NULL,
PRIMARY KEY (`adv_id_ref`)
) ENGINE = INNODB CHARSET = latin1 COLLATE = latin1_swedish_ci ;
In there look at the statement price DOUBLE NULL DEFAULT NULL,
Normally I'm using:
price DOUBLE NULL;
if I want to enable that column to accept NULL values.
So what are the differences between these 3 statements?
price DOUBLE NULL;
price DOUBLE DEFAULT NULL;
price DOUBLE NULL DEFAULT NULL;
There is no difference. NULL DEFAULT NULL is the implicit default.
From the CREATE TABLE documentation:
If neither NULL nor NOT NULL is specified, the column is treated as though NULL had been specified
From the "Data Type Default Values" chapter:
If a column definition includes no explicit DEFAULT value, MySQL determines the default value as follows: If the column can take NULL as a value, the column is defined with an explicit DEFAULT NULL clause.
In all three of the following cases:
price DOUBLE NULL;
price DOUBLE DEFAULT NULL;
price DOUBLE NULL DEFAULT NULL;
price is a double and can be null and its default value is null.
price DOUBLE NULL;
Allows the price column to accept NULL.
price DOUBLE DEFAULT NULL;
Allows the price column to accept NULL and sets the default value to NULL.
price DOUBLE NULL DEFAULT NULL;
Act the same as the second statement, as it accepts NULL values and sets the default.
Strange problem I can't seem to get my head around. I have a table in a MySQL database with the following structure...
CREATE TABLE IF NOT EXISTS `tblbaseprices` (
`base_id` bigint(11) NOT NULL auto_increment,
`base_size` int(10) NOT NULL default '0',
`base_label` varchar(250) default NULL,
`base_price_1a` float default NULL,
`base_price_2a` float default NULL,
`base_price_3a` float default NULL,
`base_price_1b` float default NULL,
`base_price_2b` float default NULL,
`base_price_3b` float default NULL,
`site_id` int(11) default NULL,
PRIMARY KEY (`base_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=134 ;
The last base_id I have in there is 132. I assume a couple of records have been deleted to auto_increment is set to 134, as you can see about. I am trying to run the following SQL statement, and when I do, I get the error "Duplicate entry '2147483647' for key 1".
INSERT INTO tblbaseprices (site_id, base_size, base_price_1a, base_price_2a, base_price_3a, base_price_4a) VALUES ('', '', '', '', '', '')
Does anybody have any ideas?
Many thanks!
2^31 − 1 = 2,147,483,647
The number 2,147,483,647 is ... the maximum value for a 32-bit signed integer in computing
2147483647 is the largest int value for mysql. Just change the type from int to bigint.
With you code I got this error - Unknown column 'base_price_4a' in 'field list'.
It means that you are trying to insert into another table (maybe in another schema), and that table has primary key INT and AUTO_INCREMENT=2147483647.
you've hit the 32-bit integer limit, thus preventing the auto increment from incrementing. switching your pk to bigint with a higher column length should fix the issue.
Also, if your PK is never going to be negative, switching to an unsigned int should give you more space.
Try changing the auto_increment column to bigint instead of int, then the max value would be '9223372036854775807' or even '18446744073709551615' if you make it unsigned (no values below 0).
Change your Auto_Increment to the last id in the column so it is continued where it left off.
Be sure you do not delete auto_increment, otherwise it will continue to produce the error.
You're inserting empty strings into numerical columns. As far as I can see, you're also inserting into a column that does not exist in the schema. My guess is this has something to do with your error.
signed and unsigned issue
alter table tblbaseprices
modify column site_id int(10) unsigned NOT NULL;
reference - http://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html
make sure unsigned for foreign key (in this case could be the site_id)
it could be caused by trigger,
there is no int(11), the max it can go is int(10)
there is no need to allow negative value for ID
to be consistently using same data type for primary key
Today I got the error duplicate key 2147483647
I think it came out when I tried to insert a record into database from PhpMyAdmin, while typing, I also tried to enter the key value and it was eider lower than the current Next autoindex or I tried to type something like 99999999999999 as the key field, and that caused it to set Next autoindex to maximum
Anyway, the erorr was caused because Next autoindex was 2147483647 for that table.
My table was empty so I fixed it by this query:
ALTER TABLE table_name AUTO_INCREMENT = 0
if your table contains data, then replace 0 with your maximum key plus 1
it's a database issue. check your phpmyadmin > your DB > structure, your primary key should be setted in "bigint", not just "int"
CREATE TABLE IF NOT EXISTS `tblbaseprices` (
`base_id` bigint(11) NOT NULL auto_increment,
`base_size` int(10) NOT NULL default '0',
`base_label` varchar(250) default NULL,
`base_price_1a` float default NULL,
`base_price_2a` float default NULL,
`base_price_3a` float default NULL,
`base_price_1b` float default NULL,
`base_price_2b` float default NULL,
`base_price_3b` float default NULL,
`site_id` int(11) default NULL,
PRIMARY KEY (`base_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=134 ;
A good explanation of that is here: http://realtechtalk.com/Duplicate_entry_2147483647_for_key_PRIMARY_MySQL_Error_Solution-2015-articles
Essentially you are trying to insert a value larger than the maximum size an INT supports which is literally the number being given to you in the error.
If you are importing data than one of the fields contains a larger value than the INT size. You could also modify your table to be a BIGINT which would take care of the issue as well (of course at the cost of extra disk space).
A common reason is that you are using some script generating large/random numbers. You should add some check to make sure the size is the same or lower than that maximum INT size of 2147483647 and you'll be good to go.
Duplicate entry '57147-2147483647' for key 'app_user' [ INSERT INTO user_lookup (user_id, app_id, app_user_id, special_offers, ip_address) VALUES ('2426569', '57147', '4009116545', 1, 1854489853) ]
Hi and thanx for reading my post i am having a little trouble learning my database in mysql.
Now i have it set up already but recently, but i had another person tell me my members table is slow and useless if i intend to have a lots of members!
I have looked it over a lot of times and did some google searches but i don't see anything wrong with it, maybe because i am new at it? can one of you sql experts look it over and tell me whats wrong with it please :)
--
-- Table structure for table `members`
--
CREATE TABLE IF NOT EXISTS `members` (
`userid` int(9) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL DEFAULT '',
`password` longtext,
`email` varchar(80) NOT NULL DEFAULT '',
`gender` int(1) NOT NULL DEFAULT '0',
`ipaddress` varchar(80) NOT NULL DEFAULT '',
`joinedon` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`acctype` int(1) NOT NULL DEFAULT '0',
`acclevel` int(1) NOT NULL DEFAULT '0',
`birthdate` date DEFAULT NULL,
`warnings` int(1) NOT NULL DEFAULT '0',
`banned` int(1) NOT NULL DEFAULT '0',
`enabled` int(1) NOT NULL DEFAULT '0',
`online` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`userid`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `emailadd` (`emailadd`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=19 ;
--
-- Dumping data for table `members`
--
It's going to be a site for faqs/tips for games, i do expect to get lots of members at one point later on but i thought i would ask to make sure it's all ok, thanx again peace.
Did the other person explain why they think it is slow and useless?
Here's a few things that I think could be improved:
email should be longer - off the top of my head, 320 should be long enough for most email addresses, but you might want to look that up.
If the int(1) fields are simple on/off fields, then they could be tinyint(1) or bool instead.
As #cularis points out, the ipaddress field might not be the appropriate type. INT UNSIGNED is better than varchar for IPv4. You can use INET_ATON() and INET_NTOA() for conversion. See:
Best Field Type for IP address?
How to store IPv6-compatible address in a relational database
As #Delan Azabani points out, your password field is too long for the value you are storing. MD5 produces a 32 character string, so varchar(32) will be sufficient. You could switch to the more secure SHA2, and use the MySQL 'SHA2()' function.
Look into using the InnoDB database engine instead of MyISAM. It offers foreign key constraints, row-level locking and transactions, amongst other things. See Should you move from MyISAM to Innodb ?.
I don't think it's necessarily slow, but I did notice that among all other text fields where you used varchar, you used longtext for the password field. This seems like you are going to store the password in the database -- don't do this!
Always take a fixed-length cryptographic hash (using, for example, SHA-1 or SHA-2) of the user's password, and put that into the database. That way, if your database server is compromised, the users' passwords are not exposed.
Apart from what #Delan said, I noted that;
JoinedOn column defined as ON UPDATE CURRENT_TIMESTAMP. If you need to maintain only the date joined, you should not update the field when the records been updated.
IPAddress column is VARCHAR(80). If you store IPv4 type IP addresses, this will be too lengthy.
Empty string ('') as DEFAULT for NOT NULL columns. Not good if intention is to have a value (other than '') on the field.
Empty string ('') as DEFAULT for UNIQUE Fields. This contradicts the contraints enforced if your intention is to have a Unique Value (other than '').
CREATE TABLE `users` (
`ID` int(10) unsigned zerofill NOT NULL auto_increment,
`username` varchar(20) NOT NULL,
PRIMARY KEY (`ID`),
KEY `Username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
what is
a) unsigned, zerofill in ID table?
b) what do you mean by KEY Username (username) ?
thank you
zerofill - left pad with 0
For example, for a column declared as INT(4) ZEROFILL, a value of 5 is retrieved as 0005.
unsigned is number not less than zero
If you specify ZEROFILL for a numeric column, MySQL automatically adds the UNSIGNED attribute to the column.
Unsigned type can be used to permit only nonnegative numbers in a column or when you need a larger upper numeric range for the column
details : http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html
KEY Username (username) ?
is an index name after Username on column username
details : http://dev.mysql.com/doc/refman/5.0/en/create-table.html
unsigned = a none positive / negative number, so you couldnt have -1 as the "-" is a sign.
zerofill = fill it with zeros by default. Not necessary as the column's already got the auto_increment / pk attributes
key = index this column i.e. make SELECTS that search on this column faster.
Ta
here is a partial answer.
a) unsigned means that the value is positive.
b) zerofill means that it will have leftpadding with '0'
ex : without zerofill you have 55 and with you will have 00000055
Regards.
Zerofill is used to pad a number with zeros instead of spaces. In this case, the number 1337 would be padded with 6 zeros and shown as 0000001337 because of int(10). Specifying unsigned is not needed since zerofill automatically chooses unsigned, see http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html
KEY foo (bar) creates an index on the bar column. The name of the index is foo.