I'm currently trying to create a mySQL database that holds hashes such as MD5 hashes. I'm using PHPmyAdmin version 3.3.9, and MySQL client version: 4.1.22
I already created a database named hashes. I'm new to mySQL so how can I add a table with data for a hash?
Hash column should be a CHAR(32) as that is the length of the hash:
CREATE TABLE `hashes` (
`id` INT NOT NULL AUTO_INCREMENT,
`hash` CHAR(32),
PRIMARY KEY (`id`)
);
mysql> describe hashes;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| hash | char(32) | YES | | NULL | |
+-------+----------+------+-----+---------+----------------+
If you want to select from the table given user input:
-- Insert sample data:
mysql> INSERT INTO `hashes` VALUES (null, MD5('hello'));
Query OK, 1 row affected (0.00 sec)
-- Test retrieval:
mysql> SELECT * FROM `hashes` WHERE `hash` = MD5('hello');
+----+----------------------------------+
| id | hash |
+----+----------------------------------+
| 1 | 5d41402abc4b2a76b9719d911017c592 |
+----+----------------------------------+
1 row in set (0.00 sec)
You can add a key on hash for better performance.
A hash can be stored as binary data or (more convenient) as text. The PHP MD5 function by default outputs a string of 32 characters, so you will need a table with a field that can hold a string of 32 character. That's all. :)
Take a look here:
http://dev.mysql.com/doc/refman/5.1/en/create-table.html
You can do it using phpMyAdmin of course but it is better to understand the actual SQL.
If you open the database (click it's name in the left hand column), there will be a "Create new table on database dbname" section. Enter the name of the table you want (e.g. hashes), and the number of fields you want.
This is where we need a bit more information: if you just want to store hashes and hashes alone then you'll need two fields: a unique hash ID (of type integer, with auto_increment set to true) and a 32 character text field. I'm a little unsure of the utility of this, so if you post a bit more information we might be able to help you out with what you're trying to achieve a little better?
Edit:
In that case, you'll need three fields: a hash id (a unique reference for each entry in the table), the hash, and the plaintext to which it correlates. Set the hash id to be an integer, with auto_increment set to true. Set the field for the hash to be varchar of length 32, and the plaintext field to 'text'.
Related
I have a MySQL 8.0.19 running in a Docker container and using the InnoDB engine. I have noticed that table integer field lengths are getting ignored.
The issue occurs with integer datatypes regardless if running a CREATE or ALTER query
CREATE TABLE `test` (
`id` int DEFAULT NULL,
`text_field` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`decimal_field` decimal(6,2) DEFAULT NULL,
`int_field` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
The lengths are showing as 0 in my MySQL client (Navicat), but the same occurs if checking in the console with SHOW FULL COLUMNS FROMtest;
mysql> SHOW FULL COLUMNS FROM `test`;
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| id | int | NULL | YES | | NULL | | select,insert,update,references | |
| text_field | varchar(20) | utf8mb4_unicode_ci | YES | | NULL | | select,insert,update,references | |
| decimal_field | decimal(6,2) | NULL | YES | | NULL | | select,insert,update,references | |
| int_field | int | NULL | YES | | NULL | | select,insert,update,references | |
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
The Type column should be showing int(11) for the two integer fields, but it isn't.
Is this related to something in my MySQL settings, and if so, which variable would have to be changed?
This is a change documented in the MySQL 8.0.19 release notes:
Display width specification for integer data types was deprecated in
MySQL 8.0.17, and now statements that include data type definitions in
their output no longer show the display width for integer types, with
these exceptions:
The type is TINYINT(1). MySQL Connectors make the assumption that
TINYINT(1) columns originated as BOOLEAN columns; this exception
enables them to continue to make that assumption.
The type includes the ZEROFILL attribute.
This change applies to tables, views, and stored routines, and affects
the output from SHOW CREATE and DESCRIBE statements, and from
INFORMATION_SCHEMA tables.
For DESCRIBE statements and INFORMATION_SCHEMA queries, output is
unaffected for objects created in previous MySQL 8.0 versions because
information already stored in the data dictionary remains unchanged.
This exception does not apply for upgrades from MySQL 5.7 to 8.0, for
which all data dictionary information is re-created such that data
type definitions do not include display width. (Bug #30556657, Bug #97680)
The "length" of an integer column doesn't mean anything. A column of int(11) is the same as int(2) or int(40). They are all a fixed-size, 32-bit integer data type. They support the same minimum and maximum value.
The "length" of integer columns has been a confusing feature of MySQL for years. It's only a hint that affects the display width, not the storage or the range of values. Practically, it only matters when you use the ZEROFILL option.
mysql> create table t ( i1 int(6) zerofill, i2 int(12) zerofill );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t set i1 = 123, i2 = 123;
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+--------+--------------+
| i1 | i2 |
+--------+--------------+
| 000123 | 000000000123 |
+--------+--------------+
1 row in set (0.00 sec)
So it's a good thing that the misleading integer "length" is now deprecated and removed. It has caused confusion for many years.
I can confirm that having upgraded AWS RDS to MySQL 8.0.19 that you can now sync using Navicat correctly.
However, PLEASE BE AWARE!!
When updating the id column, if auto_increment is set, Navicat removes auto_increment to change the length and then re-applies it at the end. This causes the auto_increment column to reassign the ids is sequencial order!
ALTER TABLE `database`.`table` MODIFY COLUMN `id` mediumint(0) NOT NULL FIRST;
...
...
ALTER TABLE `database`.`table` MODIFY COLUMN `id` mediumint(0) NOT NULL AUTO_INCREMENT;
If you are using table relationships and do not have the foreign keys setup properly, this will break your database!
Also, if you have id numbers of zero or below in your auto_increment column, this will cause the following error:
Result: 1062 - ALTER TABLE causes auto_increment resequencing,
resulting in duplicate entry '1' for key 'table.PRIMARY'
To avoid the above, you will need to manually change each tables id length to 0 and then save the changes before attempting to use the Navicat sync feature. When saving the changes using Navicat this will automatically change any other int column lengths to 0.
Please ensure you throughly test your changes on a copy of the database before trying to apply to any production databases.
I would like to add a new autoincrement column to a pre-existing table. However, I need the ids that are in that column to start at a particular value, ie
alter table MyTable
add column MyColumn int unsigned not null primary key auto_increment=999999;
Is this possible? I tried issuing:
alter table MyTable auto_increment=999999;
before I added the column, but it had no effect. Because adding the column will automatically generate the ids, it is not sufficient to run the second statement after the first.
No, it works to add an AI column with a starting position. But you almost got the syntax right. Here's a demo:
mysql> CREATE TABLE foo (v varchar(10));
mysql> INSERT INTO foo VALUES ('one'), ('two'), ('three');
Then comes the tricky syntax. You have to declare the column as AUTO_INCREMENT, but then also give the table option for the AUTO_INCREMENT starting value. And you need a comma to separate the ADD COLUMN from the table option.
mysql> ALTER TABLE foo ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY,
AUTO_INCREMENT=999999;
mysql> select * from foo;
+-------+---------+
| v | id |
+-------+---------+
| one | 999999 |
| two | 1000000 |
| three | 1000001 |
+-------+---------+
Based on various recommendations such as What data type to use for hashed password field and what length?, I could store md5 as either CHAR(32) or BINARY(16). But when I do so using BINARY(16), the stored value is identical to the first 16 characters of the CHAR(32) stored results as well as the first 16 characters of the SELECT MD5() results. What are the significance of the later 16 characters, and is their lack of presence in the binary column resulting in lost data?
CREATE TABLE test (id INT NOT NULL AUTO_INCREMENT, value VARCHAR(6), md5_char CHAR(32) NOT NULL, md5_binary BINARY(16) NOT NULL, PRIMARY KEY (id)) ENGINE = InnoDB;
INSERT INTO test(value,md5_char,md5_binary) VALUES("one!",md5("one!"),md5("one!"));
INSERT INTO test(value,md5_char,md5_binary) VALUES("two%",md5("two%"),md5("two%"));
INSERT INTO test(value,md5_char,md5_binary) VALUES("three~",md5("three~"),md5("three~"));
SELECT value,md5(value),md5_char,md5_binary FROM test;
DROP TABLE test;
+--------+----------------------------------+----------------------------------+------------------+
| value | md5(value) | md5_char | md5_binary |
+--------+----------------------------------+----------------------------------+------------------+
| one! | 633c8403325f1cf963809e6eb224d77e | 633c8403325f1cf963809e6eb224d77e | 633c8403325f1cf9 |
| two% | 48bbec047b4451a2018e0f652807b7d0 | 48bbec047b4451a2018e0f652807b7d0 | 48bbec047b4451a2 |
| three~ | fee453bb4eb68dcdfee07575e75c8cc5 | fee453bb4eb68dcdfee07575e75c8cc5 | fee453bb4eb68dcd |
+--------+----------------------------------+----------------------------------+------------------+
Currently you are losing half of the checksum when using BINARY(16). When you store an MD5 checksum in BINARY(16) you should store it as binary data, not encoded in hexadecimal. That is:
INSERT INTO test (md5_binary) VALUES(UNHEX(md5("one!")));
You can use the HEX function to encode it into hex again if you want to eye-ball compare it with another checksum:
SELECT HEX(md5_binary) FROM test;
The benefit of using BINARY to store the checksum instead of hexadecimal text is that half the storage is needed.
I have a table with various fields including a primary key, id, which is auto-incrementing:
+-------------------------------+------------------+------+-----+---------+
| Field | Type | Null | Key | Default | Extra
+-------------------------------+------------------+------+-----+---------+
| id | tinyint(11) | NO | PRI | NULL | auto_increment
The table is already populated with 114 items:
mysql> select count(*) as cnt from beer;
+-----+
| cnt |
+-----+
| 114 |
+-----+
And I am trying to insert a group of new items into the table. I am not explicitly inserting an id key. Here's a sample query:
mysql> INSERT INTO beer (name, type, alcohol_by_volume, description, image_url)
VALUES('Test Ale', 1, '4.6', '', 'https://untappd.s3.amazonaws.com/site/assets/images/temp/badge-beer-default.png');
I get the following error when attempting to manually insert that query (the insertion is actually done with a PHP script to the same results):
ERROR 1062 (23000): Duplicate entry '127' for key 1
What's going on? I thought the id would automatically increment upon insertion. I should note that the first 13 entries are blank/null for some reason, and the last key is currently 127. (it's not my table -- I'm just writing the script).
Tiny int is not the good choice for auto_increment primary key... Range is just (-128...127). Normally it's used as a flag; you need to use unsigned int
Try resetting the auto increment of primary key manually using this:
ALTER TABLE `beer` AUTO_INCREMENT = 128;
I'm looking at this Mysql question link:
And I can't repeat the behavior described in the answer to that question.
I tried creating tables with CHAR and VARCHAR column of various lengths and it doesn't matter what length - SHOW CREATE TABLE always return the data type that I've originally defined.
So - no CHAR->VARCHAR switching is going on.
Is answer to the question below only partially correct (I'm talking only about items 1 and 2)?
Q:
When you create a table, and then run SHOW CREATE TABLE on it, you occasionally get different results than what you typed in. What does MySQL modify in your newly created tables?
A (supposedly):
VARCHARs with length less than 4 become CHARs
CHARs with length more than 3 become VARCHARs.
NOT NULL gets added to the columns declared as PRIMARY KEYs
Default values such as NULL are specified for each column
There is a page in the MySQL's manual that answers some of your questions : 12.1.14.2. Silent Column Specification Changes.
Quoting some portions that correspond to items you posted in your question :
For item 3 :
Columns that are part of a PRIMARY
KEY are made NOT NULL even if not
declared that way.
About the size of varchar columns (not exactly one of your items, though) :
If strict SQL mode is not enabled, a
VARCHAR column with a length
specification greater than 65535 is
converted to TEXT, and a VARBINARY
column with a length specification
greater than 65535 is converted to
BLOB. Otherwise, an error occurs in
either of these cases.
And that page ends with the following sentence :
To see whether MySQL used a data type
other than the one you specified,
issue a DESCRIBE or SHOW CREATE
TABLE statement after creating or
altering the table.
So I'm guessing you might expect some additional differences, that are not listed.
Doing a quick test, here's a create table statement :
create table test_2 (
id int primary key,
blah_vc varchar(2),
blah_c char(5)
) engine=InnoDb;
And the table that's created gives :
mysql> desc test_2;
+---------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| blah_vc | varchar(2) | YES | | NULL | |
| blah_c | char(5) | YES | | NULL | |
+---------+------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> show create table test_2;
+--------+--------------------------------------------+
| Table | Create Table |
+--------+--------------------------------------------+
| test_2 | CREATE TABLE `test_2` (
`id` int(11) NOT NULL,
`blah_vc` varchar(2) DEFAULT NULL,
`blah_c` char(5) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+--------+--------------------------------------------+
1 row in set (0.00 sec)
So :
no : varchar has not been transformed to char
no : char has not been transformed to varchar
yes : not null has been added to primary key
well, that one is funny : describe says it hasn't,
but show create table indicates it has...
Anyway : it makes sense, for a primary key column, to not be nullable.
yes : null is specified as default for columns that can be null.
That question is pretty old, written back in the days of MySQL 4.
As of MySQL 5.0, 1 & 2 from that list are no longer true.