Formatting a temporary table - mysql

I have created a temporary table with two fields, formatted to int.
create table #tmp
unprocessed int,
invoiced int
I am then calculating a third field with this.
select unprocessed, invoiced, (unprocessed /invoiced) as percentageunprocessed
from #tmp
My result is
Unprocessed invoiced percentageunprocessed
33 200 0
It should be
33 200 0.165
I think this is because the percentageunprocessed is also formatted as int and not dec (5,2). Can I change the format?

Its not the Answer:
it not normal. normal its return a float
my version
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.15 |
+-----------+
1 row in set (0,00 sec)
mysql>
sample
mysql> CREATE TEMPORARY TABLE result (a INT, b INT);
Query OK, 0 rows affected (0,00 sec)
mysql> INSERT INTO result VALUES(10,330);
Query OK, 1 row affected (0,00 sec)
mysql> SELECT a,b,a/b FROM result;
+------+------+--------+
| a | b | a/b |
+------+------+--------+
| 10 | 330 | 0.0303 |
+------+------+--------+
1 row in set (0,00 sec)
mysql>

Related

How to modify a column to insert consequtive numbers?

So I have a table where a column that was given an auto_increment value accidentally got started form 300 instead of 1,2,3,4......i'm a beginner and i do not know how to change it back to 1,2,3,4......screenshot of table
how to change the 307, 308 to 1,2,3,4...?
I tried to update the table but that did not work.
Step-1) First take backup of your table data.
Step-2) Truncate the table by using the below SQL query.
TRUNCATE TABLE [Your_Table_Name];
Step-3) then again insert the into your table using backup data.
Alter table to drop the auto_increment, update, alter table to add the auto_increment
drop table if exists t;
create table t
( id int auto_increment primary key, val int);
insert into t values
(307,1),(308,1),(309,1),(310,1),(311,1);
alter table t
modify column id int;
#drop primary key;
show create table t;
update t
set id = id - 306;
alter table t
modify column id int auto_increment;
show create table t;
https://dbfiddle.uk/eBQh6cj8
With MySQL 8.0 you can use a window function to calculate the row numbers and then update the table:
mysql> select * from t;
+-----+------+
| id | val |
+-----+------+
| 307 | 1 |
| 308 | 1 |
| 309 | 1 |
| 310 | 1 |
| 311 | 1 |
+-----+------+
mysql> with cte as ( select id, row_number() over () as rownum from t )
-> update t join cte using (id) set id = rownum;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0
mysql> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
+----+------+
Then make sure the next id won't be a high value:
mysql> alter table t auto_increment=1;
You can try to set the auto_increment to 1, MySQL will automatically advances that to the highest id value in the table, plus 1.
Be aware that this doesn't guarantee subsequent rows will use consecutive values. You can get non-consecutive values if:
You insert greater values explicitly, overriding the auto-increment.
You roll back transactions. Id values generated by auto-increment are not recycled if you roll back.
You delete rows.
Occasionally InnoDB will skip a number anyway. It does not guarantee consecutive values — it only guarantees unique values. You should not rely on the auto-increment to be the same as a row number.
Here is a one approach to your problem.
Please take note of the following points before proceeding:
Take backup of your table in-case things do not go as expected.
Below test case has been performed on MySQL 5.7 and MyISAM Engine.
Step1: Generating dummy test table as per your test case.
mysql> CREATE TABLE t (
-> `Id` int(11) NOT NULL AUTO_INCREMENT,
-> `product_id` int(11) DEFAULT 0,
-> PRIMARY KEY (`Id`)
-> ) ENGINE=MyISAM;
Query OK, 0 rows affected (0.03 sec)
-- Inserting dummy data
mysql> INSERT INTO t VALUES (300,1);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO t VALUES (302,1);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO t VALUES (305,1);
Query OK, 1 row affected (0.00 sec)
-- Checking auto_increment value
mysql> show create table t;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) DEFAULT '0',
PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=306 DEFAULT CHARSET=latin1 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> INSERT INTO t (product_id) VALUES (2);
Query OK, 1 row affected (0.01 sec)
-- Below is the resultant table for which we need Id starting from 1,2,3 and so on...
mysql> SELECT * FROM t;
+-----+------------+
| Id | product_id |
+-----+------------+
| 300 | 1 |
| 302 | 1 |
| 305 | 1 |
| 306 | 2 |
+-----+------------+
4 rows in set (0.00 sec)
Step2: Remove AUTO_INCREMENT for the column and set the Ids manually.
-- Remove AUTO_INCREMENT
mysql> ALTER TABLE t MODIFY COLUMN Id int(11) NOT NULL;
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
-- Set the Id manually starting from 1
mysql> SET #i = 0;UPDATE t SET id = #i :=#i +1;
Query OK, 0 rows affected (0.00 sec)
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0
-- Below is the updated table with Id starting from 1,2,3 and so on...
mysql> SELECT * FROM t;
+----+------------+
| Id | product_id |
+----+------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
+----+------------+
5 rows in set (0.00 sec)
Step3: Enable AUTO_INCREMENT again for future record insertions.
-- Enable AUTO_INCREMENT again for future record insertions.
mysql> ALTER TABLE t MODIFY COLUMN Id int(11) NOT NULL AUTO_INCREMENT;
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0
-- Set the AUTO_INCREMENT value to continue from highest value of id in the table.
mysql> SELECT MAX(id+1) FROM t;
+-----------+
| MAX(id+1) |
+-----------+
| 6 |
+-----------+
1 row in set (0.00 sec)
mysql> ALTER TABLE t AUTO_INCREMENT=6;
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
-- Table is successfully modified and will have future records inserted with no gaps in Id's
mysql> INSERT INTO t (product_id) VALUES (5);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM t;
+----+------------+
| Id | product_id |
+----+------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 5 |
+----+------------+
6 rows in set (0.00 sec)
The DBCC CHECKIDENT management command is used to reset identity counter
DBCC CHECKIDENT (table_name [, { NORESEED | { RESEED [, new_reseed_value]}}])
[ WITH NO_INFOMSGS ]
EXample:
DBCC CHECKIDENT ('TestTable', RESEED, 0)
GO
many times we need to just reseed to next Id available
declare #max int
select #max=max([Id]) from [TestTable]
if #max IS NULL --check when max is returned as null
SET #max = 0
DBCC CHECKIDENT ('[TestTable]', RESEED, #max)
This will check the table and reset to the next ID.
You can get help from the link below:
Reset identity seed after deleting records in SQL Server
My mother says: the mountain that can be seen is not far away, don't stop trying

MySQL Generate Random Data

In MySQL I have some tables I need to randomize the phone numbers and Email addresses to be randomly generated for development purposes.
In MySQL how could I generate 7 digit unique random numbers for the phone numbers?
How can I generate random email address like 545165498#mailinator.com.
How can I generate this random data with MySQL Queries?
MySQL rand() Returns a random floating-point value in the range 0 <= value < 1.0.
Multiply that by another number: UPPER_BOUND and get the floor of that, and you will get a random integer between 0 and (UPPER_BOUND-1) like this:
SELECT floor(rand() * 10) as randNum;
That will give you only one random number between 0 and 10.
Change the 10 to the number one higher than you want to generate.
Something like this :
UPDATE user
SET email = CONCAT(FLOOR(rand() * 10000000),'#mailinator.com'),
PhoneNo = FLOOR(rand() * 10000000)
This should give you a random number of 7 digits length
SELECT FLOOR(1000000 + RAND() * 8999999)
And something like this should update your phone numbers and e-mail addresses according to your requirement
UPDATE Customers
SET phone = CAST(FLOOR(1000000 + RAND(8999999) AS VARCHAR),
email = CONCAT(CAST(FLOOR(1000000 + RAND(8999999) AS VARCHAR), '#mailinator.com')
MySQL Generate random data walkthrough:
Random number between 0 (inclusive) and 1 exclusive:
mysql> select rand();
+--------------------+
| rand() |
+--------------------+
| 0.5485130739850114 |
+--------------------+
1 row in set (0.00 sec)
Random int between 0 (inclusive) and 10 exclusive:
mysql> select floor(rand()*10);
+------------------+
| floor(rand()*10) |
+------------------+
| 6 |
+------------------+
1 row in set (0.00 sec)
Random letter or number:
mysql> select concat(substring('ABCDEF012345', rand()*36+1, 1));
+---------------------------------------------------------------------------+
| concat(substring('ABCDEF012345', rand()*36+1, 1)) |
+---------------------------------------------------------------------------+
| F |
+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
Random letter a to z:
mysql> select char(round(rand()*25)+97);
+---------------------------+
| char(round(rand()*25)+97) |
+---------------------------+
| s |
+---------------------------+
1 row in set (0.00 sec)
Random 8 character alphanumeric string:
mysql> SELECT LEFT(UUID(), 8);
+-----------------+
| LEFT(UUID(), 8) |
+-----------------+
| c26117af |
+-----------------+
1 row in set (0.00 sec)
Random capital letter in MySQL:
mysql> select CHAR( FLOOR(65 + (RAND() * 25)));
+----------------------------------+
| CHAR( FLOOR(65 + (RAND() * 25))) |
+----------------------------------+
| B |
+----------------------------------+
1 row in set (0.00 sec)
Load a random row into a table:
mysql> create table penguin (id INT primary key auto_increment, msg TEXT);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into penguin values (0, LEFT(UUID(), 8));
Query OK, 1 row affected (0.00 sec)
mysql> select * from penguin;
+------+----------+
| id | msg |
+------+----------+
| 0 | abab341b |
+------+----------+
1 row in set (0.00 sec)
Load random rows:
Make a procedure called dennis that loads 1000 random rows into penguin.
mysql> delimiter ;;
mysql> drop procedure if exists dennis;;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> create procedure dennis()
-> begin
-> DECLARE int_val INT DEFAULT 0;
-> myloop : LOOP
-> if (int_val = 1000) THEN
-> LEAVE myloop;
-> end if;
-> insert into penguin values (0, LEFT(UUID(), 8));
-> set int_val = int_val +1;
-> end loop;
-> end;;
Query OK, 0 rows affected (0.00 sec)
mysql> call dennis();;
mysql> select * from penguin;;
+------+----------+
| id | msg |
+------+----------+
| 0 | abab341b |
| 1 | c5dc08ee |
| 2 | c5dca476 |
...
+------+----------+
Update all rows in a table to have random data:
mysql> create table foo (id INT primary key auto_increment, msg TEXT);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into foo values (0,'hi');
Query OK, 1 row affected (0.00 sec)
mysql> insert into foo values (0,'hi2');
Query OK, 1 row affected (0.00 sec)
mysql> insert into foo values (0,'hi3');
Query OK, 1 row affected (0.00 sec)
mysql> select * from foo;
+----+------+
| id | msg |
+----+------+
| 1 | hi |
| 2 | hi2 |
| 3 | hi3 |
+----+------+
3 rows in set (0.00 sec)
mysql> update foo set msg = rand();
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3 Changed: 3 Warnings: 0
mysql> select * from foo;
+----+---------------------+
| id | msg |
+----+---------------------+
| 1 | 0.42576668451145916 |
| 2 | 0.6385560879842901 |
| 3 | 0.9154804171207178 |
+----+---------------------+
3 rows in set (0.00 sec)
Here is an online tool to generate random data with many options. http://www.generatedata.com/
Just enter the parameters to define what kind of random data you want, and export it to the appropriate format, then you can load it.

INT(3) column not cliping the value to appropriate length and allowing the full value to be inserted - MySQL

I have an INT(3) UNSIGNED column. If I insert a value with character length more that 3, it doesn't clip that value but inserts it.
Whats happening?
FROM What does "size" in int(size) of MySQL mean?
Finally, let's come to the place of the manual where there is the
biggest hint to what the number means:
Several of the data type descriptions use these conventions:
M indicates the maximum display width for integer types. For
floating-point and fixed-point types, M is the total number of digits
that can be stored. For string types, M is the maximum length. The
maximum allowable value of M depends on the data type.
It's about the display width. The weird thing is, though2, that, for
example, if you have a value of 5 digits in a field with a display
width of 4 digits, the display width will not cut a digits off.
If the value has less digits than the display width, nothing happens
either. So it seems like the display doesn't have any effect in real
life.
Now2 ZEROFILL comes into play. It is a neat feature that pads values
that are (here it comes) less than the specified display width with
zeros, so that you will always receive a value of the specified
length. This is for example useful for invoice ids.
So, concluding: The size is neither bits nor bytes. It's just the
display width, that is used when the field has ZEROFILL specified.
mysql> create table a ( a tinyint );
Query OK, 0 rows affected (0.29 sec)
mysql> show columns from a;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| a | tinyint(4) | YES | | NULL | |
+-------+------------+------+-----+---------+-------+
1 row in set (0.26 sec)
mysql> alter table a change a a tinyint(1);
Query OK, 0 rows affected (0.09 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> insert into a values (100);
Query OK, 1 row affected (0.00 sec)
mysql> select * from a;
+-----+
| a |
+-----+
| 100 |
+-----+
1 row in set (0.00 sec)
2 Some code to better explain what I described so clumsily.
mysql> create table b ( b int (4));
Query OK, 0 rows affected (0.25 sec)
mysql> insert into b values (10000);
Query OK, 1 row affected (0.00 sec)
mysql> select * from b;
+-------+
| b |
+-------+
| 10000 |
+-------+
1 row in set (0.00 sec)
mysql> alter table b change b b int(11);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from b;
+-------+
| b |
+-------+
| 10000 |
+-------+
1 row in set (0.00 sec)
mysql> alter table b change b b int(11) zerofill;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from b;
+-------------+
| b |
+-------------+
| 00000010000 |
+-------------+
1 row in set (0.00 sec)
mysql> alter table b change b b int(4) zerofill;
Query OK, 1 row affected (0.08 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from b;
+-------+
| b |
+-------+
| 10000 |
+-------+
1 row in set (0.00 sec)
mysql> alter table b change b b int(6) zerofill;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from b;
+--------+
| b |
+--------+
| 010000 |
+--------+
1 row in set (0.00 sec)
actually 3 there is a display width which works for ZEROFILL that pads zero on the right. It doesn't limit the capacity of the integer as it stores upto 4294967295 starting from zero.
example,
CREATE TABLE tableName
(
x INT(3) ZEROFILL NOT NULL,
y INT NOT NULL
);
INSERT INTO tableName (x,y) VALUES
(1, 1),
(12, 12);
SELECT x, y FROM tableName;
Result:
x y
001 1
012 12
Using display width has no effect on how the data is stored. It affects only how it is displayed.
Integer Types (Exact Value)

mysql delete triggers

I think I read that the delete trigger doesn't know what data was deleted and loops over the whole table applying the trigger. Is that true?
Does that mean that the before delete loops over the whole table before the data is deleted and after delete loops over the whole table after the delete occurs?
Is there no way to loop over just the deleted records? So If 10 records are deleted loop over them?
DELIMITER $$
DROP TRIGGER `before_delete_jecki_triggername`$$
CREATE TRIGGER before_delete_triggername
BEFORE DELETE ON table
FOR EACH ROW
BEGIN
/*do stuff*/
END$$
DELIMITER ;
Thanks,
Mat
I think it was due to a confusion with FOR EACH ROW statement.
It is only for "matched records for the statement issued before trigger is invoked."
If there exists N number of records in a table and matches records for where id=x,
assuming x causes a result of less than N records, say N-5, then
FOR EACH ROW causes a loop for N-5 times only.
UPDATE:
A sample test run on the rows affected due to FOR EACH ROW statement is shown below.
mysql> -- create a test table
mysql> drop table if exists tbl; create table tbl ( i int, v varchar(10) );
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.06 sec)
mysql> -- set test data
mysql> insert into tbl values(1,'one'),(2,'two' ),(3,'three'),(10,'ten'),(11,'eleven');
Query OK, 5 rows affected (0.02 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from tbl;
+------+--------+
| i | v |
+------+--------+
| 1 | one |
| 2 | two |
| 3 | three |
| 10 | ten |
| 11 | eleven |
+------+--------+
5 rows in set (0.02 sec)
mysql> select count(*) row_count from tbl;
+-----------+
| row_count |
+-----------+
| 5 |
+-----------+
1 row in set (0.00 sec)
mysql>
mysql> -- record loop count of trigger in a table
mysql> drop table if exists rows_affected; create table rows_affected( i int );
Query OK, 0 rows affected (0.02 sec)
Query OK, 0 rows affected (0.05 sec)
mysql> select count(*) 'rows_affected' from rows_affected;
+---------------+
| rows_affected |
+---------------+
| 0 |
+---------------+
1 row in set (0.00 sec)
mysql>
mysql> set #cnt=0;
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> -- drop trigger if exists trig_bef_del_on_tbl;
mysql> delimiter //
mysql> create trigger trig_bef_del_on_tbl before delete on tbl
-> for each row begin
-> set #cnt = if(#cnt is null, 1, (#cnt+1));
->
-> /* for cross checking save loop count */
-> insert into rows_affected values ( #cnt );
-> end;
-> //
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> delimiter ;
mysql>
mysql> -- now let us test the delete operation
mysql> delete from tbl where i like '%1%';
Query OK, 3 rows affected (0.02 sec)
mysql>
mysql> -- now let us see what the loop count was
mysql> select #cnt as 'cnt';
+------+
| cnt |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
mysql>
mysql> -- now let us see the table data
mysql> select * from tbl;
+------+-------+
| i | v |
+------+-------+
| 2 | two |
| 3 | three |
+------+-------+
2 rows in set (0.00 sec)
mysql> select count(*) row_count from tbl;
+-----------+
| row_count |
+-----------+
| 2 |
+-----------+
1 row in set (0.00 sec)
mysql> select count(*) 'rows_affected' from rows_affected;
+---------------+
| rows_affected |
+---------------+
| 3 |
+---------------+
1 row in set (0.00 sec)
mysql>

using a mysql trigger to copy and paste value within the same row, is it possible?

I have a form in which the user enters their e-mail address along with their username and desired password. How would I go about creating a trigger that will copy the e-mail address into the username field (located in the same row) if the user doesn't select a user name?
Table: Users
+-------+---------+------+-----+---------+
| uName | uPassword | uEmail |
+-------+---------+------+-----+---------+
| NULL | pass123 | uzr#sql.com |
+-------+---------+------+-----+---------+
Are you sure you need a trigger to do that? If you have control over your insert or update statement (which you may not if you're using an ORM) you can do something like this:
mysql> insert into t4 (uemail, upassword, uname) SELECT #email:='joe#joe.com', 'secretpassword', ifnull(null, #email);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from t4 where uemail='joe#joe.com';
+-------------+----------------+-------------+
| uname | upassword | uemail |
+-------------+----------------+-------------+
| joe#joe.com | secretpassword | joe#joe.com |
+-------------+----------------+-------------+
1 row in set (0.00 sec)
If you don't have control over the insert/update statements, then yes, you can use a trigger for that:
mysql> create trigger setuname before insert on t4
-> for each row begin
-> set new.uname=ifnull(new.uname, new.uemail);
-> end;
-> |
Query OK, 0 rows affected (0.09 sec)
mysql> delimiter ;
mysql> insert into t4 (uname, uemail, upassword) values (null, 'joe#joe.com', 'secretpassword');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t4;
+-------------+----------------+-------------+
| uname | upassword | uemail |
+-------------+----------------+-------------+
| joe#joe.com | secretpassword | joe#joe.com |
+-------------+----------------+-------------+
1 row in set (0.00 sec)