mysql aes_encrypt into longtext column - mysql

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.

Related

Display id with zero as starting number [duplicate]

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!" ;-)

ERROR 1048 (23000) Column cannot be NULL, however I am inserting valid data

There are tons of these posts on Stack Overflow, however from the 20 or so that I looked at they were either coding errors faced when interfacing with MySQL (which I am not trying to do) or simply wanted null values but had their table defined incorrectly.
I am seeing an error in MySQL 5.6.19 where I have a column that is not allowed to have a null value. This is fine as it shouldn't have a null value. Here is the table desc below.
mysql> describe z;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| a | int(11) | NO | PRI | NULL | auto_increment |
| data | char(30) | NO | | NULL | |
| t | datetime | YES | | NULL | |
+-------+----------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
My problem is that I am inserting valid data....
mysql> insert into z (data, t) values('helloworld', sysdate());
ERROR 1048 (23000): Column 'data' cannot be null
There is one other piece of information that might be of some concern... or may not be.
I have a trigger and procedure that execute upon the implementation of inserts into this column. However I don't see that it should be a problem due to the trigger being activated after the insert statement completes.
Here is the trigger:
mysql> show triggers\G
*************************** 1. row ***************************
Trigger: insertuser
Event: INSERT
Table: z
Statement: begin
call triggerproc(sysdate(),user(),(select data from z where a = last_insert_id()));
end
Timing: AFTER
Created: NULL
sql_mode: NO_ENGINE_SUBSTITUTION
Definer: root#localhost
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.00 sec)
And the Procedure:
mysql> show create procedure triggerproc\G
*************************** 1. row ***************************
Procedure: triggerproc
sql_mode: NO_ENGINE_SUBSTITUTION
Create Procedure: CREATE DEFINER=`root`#`localhost` PROCEDURE `triggerproc`(in a datetime, in b char(30), in c char(30))
begin
insert into record (t,u,data) values(a,b,c);
end
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.00 sec)
Just for good measure I will include the definition for the record table as well.
mysql> desc record;
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| t | datetime | NO | | NULL | |
| u | char(30) | NO | | NULL | |
| data | char(30) | NO | | NULL | |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)
I have looked through the MySQL reference manual for anything that could be of use, however it doesn't seem to have any details on this other than the standard error and to check that your column is not defined as not null... or I missed it...
In any case I would be greatly appreciative if anyone can help me out with finding out either the reason for this error or how I can go about finding the reason.
Thanks in advance.
EDIT: My question was answered wonderfully by TheConstructor he informed me that to grab new information from a column that was just inserted through a trigger that the NEW.column operator may be used. Furthermore he followed up with documentation that helps to understand this issue located at Trigger Syntax.
I only wonder why the trigger that I had wouldn't work with the insert statement even though it should activate after the previous statement, which makes me believe that it should (theoretically) work.
Reading the documentation on LAST_INSERT_ID() I would suggest that the value is only updated after the last trigger runs. I also created a trigger which inserts the result of LAST_INSERT_ID() into another table and it would always insert the id of the row inserted by the INSERT statement before or 0 if there was no previous INSERT.
From within an insert or update trigger you can always refer to the state after the statement by using NEW.column where column is a column-name of your table. See the documentation for examples

Change column data type in MySQL without losing other metadata (DEFAULT, NOTNULL...)

If I do:
ALTER TABLE testtable MODIFY mycolumn NEWDATATYPE;
I loose other definitions like NOT NULL, COMMENTS, DEFAULT values... Is there a way to do it?
In PostgreSQL I used:
ALTER TABLE testtable ALTER COLUMN mycolumn NEWDATATYPE;
And it does what is supposed to: change the column datatype, without touching any other definition, only giving error if data types were not compatible and so on (but you can specify USING).
I'll try a workaround, but I did a query to identify several columns across different tables to update the datatype and now I've identified that this data was lost, so I'll have to redo it considering these informations too.
As it's stated in manual page, ALTER TABLE requires all new type attributes to be defined.
However, there is a way to overcome this. You may use INFORMATION_SCHEMA meta-data to reconstruct desired ALTER query. for example, if we have simple table:
mysql> DESCRIBE t;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| value | varchar(255) | NO | | NULL | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
then we can reproduce our alter statement with:
SELECT
CONCAT(
COLUMN_NAME,
' #new_type',
IF(IS_NULLABLE='NO', ' NOT NULL ', ' '),
EXTRA
) AS s
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA='test'
AND
TABLE_NAME='t'
the result would be:
+--------------------------------------+
| s |
+--------------------------------------+
| id #new_type NOT NULL auto_increment |
| value #new_type NOT NULL |
+--------------------------------------+
Here I've left #new_type to indicate that we can use variable for that (or even substitute our new type directly to query). With variable that would be:
Set our variables.
mysql> SET #new_type := 'VARCHAR(10)', #column_name := 'value';
Query OK, 0 rows affected (0.00 sec)
Prepare variable for prepared statement (it's long query, but I've left explanations above):
SET #sql = (SELECT CONCAT('ALTER TABLE t CHANGE `',COLUMN_NAME, '` `', COLUMN_NAME, '` ', #new_type, IF(IS_NULLABLE='NO', ' NOT NULL ', ' '), EXTRA) AS s FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t' AND COLUMN_NAME=#column_name);
Prepare statement:
mysql> prepare stmt from #sql;
Query OK, 0 rows affected (0.00 sec)
Statement prepared
Finally, execute it:
mysql> execute stmt;
Query OK, 0 rows affected (0.22 sec)
Records: 0 Duplicates: 0 Warnings: 0
Then we'll get our data type changed to VARCHAR(10) with saving all the rest specifiers:
mysql> DESCRIBE t;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| value | varchar(10) | NO | | NULL | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
ALTER TABLE tableName
MODIFY COLUMN columnName datatype
When you use CHANGE or MODIFY in ALTER table_name, column_definition must include the data type and all attributes that should apply to the new column, other than index attributes such as PRIMARY KEY or UNIQUE. Attributes present in the original definition but not specified for the new definition are not carried forward.
Suppose that a column col1 is defined as INT UNSIGNED DEFAULT 1 COMMENT 'my column' and you modify the column as follows:
ALTER TABLE t1 MODIFY col1 BIGINT;
The resulting column will be defined as BIGINT, but will not include the attributes UNSIGNED DEFAULT 1 COMMENT 'my column'. To retain them, the statement should be:
ALTER TABLE t1 MODIFY col1 BIGINT UNSIGNED DEFAULT 1 COMMENT 'my column';
When you change a data type using CHANGE or MODIFY, MySQL tries to convert existing column values to the new type as well as possible.
See the documentation.

Why "NOT NULL" Doesn't Work in MySQL Client

I am using MySQL client of version 5.5. Today I tried "NOT NULL" to set an attribute, only find it doesn't work during my test. Anybody helps explain this?
//Create Table
CREATE TABLE state(
state_cd char(2) NOT NULL,
state_name varchar(30)
);
//Insert an "Invalid" Record
INSERT INTO state(state_name)
values('Massachusetts');
//DB Operation succeeds!!!
Query OK, 1 row affected, 1 warning (0.09 sec)
//Check the table
mysql> select * from state;
+----------+---------------+
| state_cd | state_name |
+----------+---------------+
| | Massachusetts |
+----------+---------------+
1 row in set (0.00 sec)
mysql> describe state;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| state_cd | char(2) | NO | | NULL | |
| state_name | varchar(30) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
If you try to insert or update a NOT NULL column to NULL, MySQL will set it to the default instead (in this case the de-facto default is empty string). MySQL will also issue a warning that you can see with SHOW WARNINGS that should say something about an incorrect column value. It will not prevent you from attempting to insert a null value, but it will not accept the value.
You may want to specify an explicit default value
state_cd char(2) NOT NULL DEFAULT '--'
If you want the query to fail when attempting you can either handle this at the application level or take a look at MySQL server modes, which you can set to TRADITIONAL so INSERT/UPDATE will fail when attempting to add an incorrect value.

Set bigint length to infinity

I am trying to set the length to infinity of one of the field of my database table whose data type is integer (BIGINT). Kindly let me know how can I set the length of the field to infinity/unlimited?
Column Type Collation Attributes Null Default Extra Action
1 id bigint(255) No None AUTO_INCREMENT
You cannot. All *INT fields have a fixed length that directly relates to the size of integers in various programming languages (and in particular, C). Even DECIMAL has a maximum size. If you need larger than it provides then use one of the *TEXT fields to hold the value as a string, but be aware that even those have limitations.
For maximum values take a look at documentation
BIGINT SIGNED - 9223372036854775807
BIGINT UNSIGNED - 18446744073709551615
mysql> CREATE TABLE Table1(`col1` BIGINT, `col2` BIGINT UNSIGNED);
Query OK, 0 rows affected (0.02 sec)
mysql> DESC table1;
+-------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| col1 | bigint(20) | YES | | NULL | |
| col2 | bigint(20) unsigned | YES | | NULL | |
+-------+---------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> INSERT INTO Table1 VALUES(9223372036854775807, 18446744073709551615);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM Table1;
+---------------------+----------------------+
| col1 | col2 |
+---------------------+----------------------+
| 9223372036854775807 | 18446744073709551615 |
+---------------------+----------------------+
1 row in set (0.00 sec)
I think it is not allowed in DBMS, but some DBMS like MSDE 2000 can accept the infinite float value. but it is a fatal error if you save this value.
i mean are sure your application needs such kind of data without having no errors. ?
BIGINT range is:
-9223372036854775808 to 9223372036854775807 normal. 0 to 18446744073709551615 UNSIGNED*.
The maximum number of digits may be specified in parenthesis
if you query this infinite OR NaN data , your DB may corrupt or throw a fatal error.
That is why it is recommned to better use Exceptional handling before querying if you have no idea about the stored data.