How can I make MySQL auto increment in 4 digit format?
So instead of '1' make '0001'?
Try adding ZEROFILL attribute to the field.
Could you leave it as an integer and format it for humans in your SQL, for example, to pad with zeros to 4 chars wide
select lpad(idcolumn,4,'0') from mytable;
Or use zerofill and specify the desired width when declaring the table:
create table tmpfoo (
mykey int(6) zerofill not null auto_increment,
primary key(mykey)
);
insert into tmpfoo values(1),(2);
select * from tmpfoo;
+--------+
| mykey |
+--------+
| 000001 |
| 000002 |
+--------+
MySQL supports ZEROFILL on integer columns:
mysql> create table foo (the_key int unsigned zerofill not null
auto_increment primary key);
Query OK, 0 rows affected (0.21 sec)
mysql> insert into foo SET the_key = Null;
Query OK, 1 row affected (0.00 sec)
...
mysql> insert into foo SET the_key = Null;
Query OK, 1 row affected (0.00 sec)
mysql> select * from foo;
+------------+
| the_key |
+------------+
| 0000000001 |
| 0000000002 |
| 0000000003 |
| 0000000004 |
| 0000000005 |
| 0000000006 |
| 0000000007 |
| 0000000008 |
+------------+
8 rows in set (0.00 sec)
You may need to look into using a smallint (5 digits), or trimming/padding.
If you need the auto_increment column in a zero padded format, I suggest that you display it as such and not attempt to store it in the database that way.
In PHP, you could use the following code to display or otherwise use the id:
$padded_id = str_pad($id, 4, '0');
To pad in the database set the id column to ZEROFILL
But if its for display purposes only I recommend using LPAD
SELECT RIGHT('000000' + yourNum, 6);
is the field an integer? if so, the answer is, "why? it's an integer!" ;-)
Related
I'm trying to write an update that will increment the value of auth_id; however, if there is no value, I'd like to set it to 1. I can't even get the select to give me a 0 value to increment.
mysql> describe sequences;
+---------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------------------+------+-----+---------+-------+
| auth_id | int(5) unsigned zerofill | NO | | 00000 | |
+---------+--------------------------+------+-----+---------+-------+
I thought this would work.
mysql> select ifnull(auth_id,0) from sequences;
Empty set (0.00 sec)
Or this...
mysql> select coalesce(auth_id, 0) from sequences;
Empty set (0.00 sec)
What am I missing?
This seems to work:
select ifnull(sequences.auth_id, x.auth_id) as auth_id from sequences right join (select 1 as auth_id) x on 1;
The assumption is that there's only 1 row in sequences. The trick is to make a right join to a fake table with only one row of its own, and then use the ifnull to get the wanted value.
I have a mySQL (InnoDB) table:
belegID int NOT_NULL PRIMARY_KEY AUTO_INCREMENT,
docNum int NOT_NULL,
docYear date NOT_NULL,
.... -- more columns
I need the following relations:
belegID is the primary key (unique ID).
docNum is also a (unique) ID but related to the year. Each year starts by 1.
How can I solve this on mySQL side and how can I get the next docNum (ID related to the year)?
Thank you in advance.
You can use triggers to resolve your issue. Here is simple example (don't forget to rename schema and table if you'll try to use that):
DELIMITER //
CREATE TRIGGER fillDocNumber BEFORE INSERT ON test.t
FOR EACH ROW
BEGIN
SET #maxNum = (SELECT MAX(docNum) FROM test.t WHERE YEAR(docYear)=YEAR(NEW.docYear));
IF #maxNum IS NULL THEN
SET NEW.docNum=1;
ELSE
SET NEW.docNum=#maxNum+1;
END IF;
END;//
DELIMITER ;
Let's assume we have table:
CREATE TABLE `t` (
`belegID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`docNum` int(11) unsigned DEFAULT NULL,
`docYear` date NOT NULL,
PRIMARY KEY (`belegID`)
) ENGINE=InnoDB;
After creating our trigger we'll populate it with some data:
mysql> insert into t (docYear) values ('2013-04-06');
Query OK, 1 row affected (0.13 sec)
mysql> insert into t (docYear) values ('2012-02-18');
Query OK, 1 row affected (0.05 sec)
mysql> insert into t (docYear) values ('2013-12-11');
Query OK, 1 row affected (0.02 sec)
mysql> insert into t (docYear) values ('2014-10-30');
Query OK, 1 row affected (0.07 sec)
mysql> insert into t (docYear) values ('2014-01-03');
Query OK, 1 row affected (0.06 sec)
and now it's our result:
mysql> select * from t;
+---------+--------+------------+
| belegID | docNum | docYear |
+---------+--------+------------+
| 1 | 1 | 2013-04-06 |
| 2 | 1 | 2012-02-18 |
| 3 | 2 | 2013-12-11 |
| 4 | 1 | 2014-10-30 |
| 5 | 2 | 2014-01-03 |
+---------+--------+------------+
5 rows in set (0.00 sec)
Quite as expected.
Hint: rename field docYear, it's confusing. Correct name would be docDate (or store year in it and document's date in separate field - in fact, that will increase performance since then you'll be able to create index by it and get rid of YEAR() function in calculating MAX within trigger - and so index will be used).
I discovered something strange today when I was trying to select sum from an ENUM field. It was adding 1 to the values! A sample table I used is shown below:
x y
_______
3 | 2
0 | 1
Both x and y are ENUM ('0','1','2','3')
My query is as follows:
select sum(x), sum(y), sum(x+y) from myfield
And the result is:
5 5 10
This is very strange. Does it mean that is this behaviour consistent? Can I use something like:
select sum(x - 1), sum(y - 1), sum((x-1)+(y-1)) from myfield
which will produce the correct results or is this behavior only peculiar to my db server in particular?
Thanks.
EDIT:
For those wondering why I'm using ENUM, it's because the actual field I'm using contains 'AR' which can't fit in into tinyint.
As an ENUM field is really just an INT UNSIGNED, it will not work as you expect, if you use integer values for the ENUMs. For example, your ENUM of '0', is stored internally as a numeric 1, and your '1', is stored as a numeric 2. Surprisingly, the empty string '' is stored internally as a 0. Here's an example of this not working as expected:
mysql> CREATE TABLE enumtest (
-> id int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> a ENUM ('0','1','2','3') NOT NULL DEFAULT '0',
-> i int unsigned NOT NULL DEFAULT 0
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO enumtest SET a = 0, i=0;
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------+
| Warning | 1265 | Data truncated for column 'a' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)
mysql> INSERT INTO enumtest SET a = '0', i=0;
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO enumtest SET a = 1, i=1;
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO enumtest SET a = '1', i=1;
Query OK, 1 row affected (0.00 sec)
mysql> SELECT a,0+a,i FROM enumtest;
+---+-----+---+
| a | 0+a | i |
+---+-----+---+
| | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 1 | 1 |
| 1 | 2 | 1 |
+---+-----+---+
4 rows in set (0.00 sec)
mysql> SELECT SUM(a),SUM(0+a), SUM(i) FROM enumtest;
+--------+----------+--------+
| SUM(a) | SUM(0+a) | SUM(i) |
+--------+----------+--------+
| 4 | 4 | 2 |
+--------+----------+--------+
1 row in set (0.00 sec)
The clause 0+a coerces the ENUM to its underlying UNSIGNED value. This is equivalent to CAST(a AS UNSIGNED).
This is because doing SUM() on an enum column doesn't do what you think it does. The data stored for an enum column type is the index into the enum, that index starts at 1, and it's this index that mysql will SUM()
Your table looks like this when displayed:
x y
_______
3 | 2
0 | 1
This is showing your enum values - you just happened to define your enum values to be numbers too. You could have defined them to be e.g. ENUM ('blue','red','green','yellow')
And it would have looked like:
x y
_______________
yellow | green
blue | red
However, this is for display only. What is actually stored in the rows for this table is
the index in the enum.
The elements listed in the column specification are assigned index
numbers, beginning with 1.
So those indexes starts at 1. it's these underlying data that SUM() and other aggregate functions works at for an ENUM column. There's no implicit conversion to the enum values, which you defined as numbers too.
i.e. the data stored is these indexes:
x y
_______
4 | 3
1 | 2
And while it doesn't really make sense to SUM enums, it is those indexes that mysql would aggregate when using SUM()
The docs is a must read.
I knew boolean in mysql as tinyint (1).
Today I see a table with defined an integer like tinyint(2), and also others like int(4), int(6) ...
What does the size means in field of type integer and tinyint ?
The (m) indicates the column display width; applications such as the MySQL client make use of this when showing the query results.
For example:
| v | a | b | c |
+-----+-----+-----+-----+
| 1 | 1 | 1 | 1 |
| 10 | 10 | 10 | 10 |
| 100 | 100 | 100 | 100 |
Here a, b and c are using TINYINT(1), TINYINT(2) and TINYINT(3) respectively. As you can see, it pads the values on the left side using the display width.
It's important to note that it does not affect the accepted range of values for that particular type, i.e. TINYINT(1) still accepts [-128 .. 127].
It means display width
Whether you use tinyint(1) or tinyint(2), it does not make any difference.
I always use tinyint(1) and int(11), I used several mysql clients (navicat, sequel pro).
It does not mean anything AT ALL! I ran a test, all above clients or even the command-line client seems to ignore this.
But, display width is most important if you are using ZEROFILL option, for example your table has following 2 columns:
A tinyint(2) zerofill
B tinyint(4) zerofill
both columns has the value of 1, output for column A would be 01 and 0001 for B, as seen in screenshot below :)
mysql> CREATE TABLE tin3(id int PRIMARY KEY,val TINYINT(10) ZEROFILL);
Query OK, 0 rows affected (0.04 sec)
mysql> INSERT INTO tin3 VALUES(1,12),(2,7),(4,101);
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM tin3;
+----+------------+
| id | val |
+----+------------+
| 1 | 0000000012 |
| 2 | 0000000007 |
| 4 | 0000000101 |
+----+------------+
3 rows in set (0.00 sec)
mysql>
mysql> SELECT LENGTH(val) FROM tin3 WHERE id=2;
+-------------+
| LENGTH(val) |
+-------------+
| 10 |
+-------------+
1 row in set (0.01 sec)
mysql> SELECT val+1 FROM tin3 WHERE id=2;
+-------+
| val+1 |
+-------+
| 8 |
+-------+
1 row in set (0.00 sec)
About the INT, TINYINT... These are different data types, INT is 4-byte number, TINYINT is 1-byte number. More information here - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT.
The syntax of TINYINT data type is TINYINT(M), where M indicates the maximum display width (used only if your MySQL client supports it).
Numeric Type Attributes.
Is it possible to store a MySQL AES_ENCRYPT into a LONGTEXT column?
I know I'm suppose to use varbinary or blob, but I have a table that I'm storing a bunch of random "settings" in, and the settings_value column is longtext.
I went to store a "smtp mail password" in there, and got a little stuck.
If not, I guess, I'll store it as a hex string through php.
SOLUTION:
My query was something like this:
INSERT INTO table (setting_value)VALUES(AES_ENCRYPT('password', 'key')) ON DUPLICATE KEY UPDATE setting_value=VALUES(setting_value)
As you will see in my comments below, I tried changing my column encoding from utf8_unicode_ci to utf8_bin and still it failed. I changed to latin1_bin and it worked.
I switched back to utf8_unicode_ci and changed my query to the following:
INSERT INTO table (setting_value)VALUES(HEX(AES_ENCRYPT('password', 'key'))) ON DUPLICATE KEY UPDATE setting_value=VALUES(setting_value)
That worked since it just turned my value into a hex string.
Took me a second to figure out how to get the value back out correctly, so for documentation purposes:
$pass = SELECT AES_DECRYPT(BINARY(UNHEX(setting_value)), 'key') as orig_text FROM table
echo $pass->orig_text
Did you try it? It's pretty easy to set up a test case, and from what I can see it works fine for your requirements:
mysql> create table t (id int unsigned not null auto_increment primary key, str LONGTEXT);
Query OK, 0 rows affected (0.13 sec)
mysql> desc t;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| str | longtext | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.05 sec)
mysql>
mysql> INSERT INTO t VALUES (1,AES_ENCRYPT('text','password'));
Query OK, 1 row affected (0.02 sec)
mysql>
mysql> select id,str,AES_DECRYPT(str,'password') from t;
+----+-----------------------------+-----------------------------+
| id | str | AES_DECRYPT(str,'password') |
+----+-----------------------------+-----------------------------+
| 1 | ö½¨Ü·øÍJ/ª¼Tf€D | text |
+----+-----------------------------+-----------------------------+
1 row in set (0.00 sec)
Use some binary column type (like BLOB instead of LONGTEXT) for storing AES_ENCRYPTed content.