I would like to insert data in MySQL with automatic naming on field username but how i can do it?.
Currently data at table is:
+----+----------+
| id | username |
+----+----------+
| 1 | admin1 |
| 2 | admin2 |
+----+----------+
I try using this sql but it's can't:
INSERT INTO `tbl_user` (
`username`
)
VALUES (
CONCAT('admin',(SELECT MAX(SUBSTRING_INDEX(`username`,'admin',-1))+1 FROM `tbl_user`))
);
and get error message #1093 - You can't specify target table 'tbl_user' for update in FROM clause
Final result i want is:
+----+----------+
| id | username |
+----+----------+
| 1 | admin1 |
| 2 | admin2 |
| 6 | admin3 |
| 9 | admin4 |
+----+----------+
is that possible? thanks.
You can use a trigger that would update the column username after an insert. Here's some more information on how to actually do this: http://www.roseindia.net/sql/trigger/mysql-trigger-after-insert.shtml
Edit
I forgot that MySQL won't allow you to update a table from a trigger declared on the same table.
However, this should do what you're trying to do:
SET #id := (SELECT id FROM YOUR_TABLE ORDER BY id DESC LIMIT 1);
INSERT INTO YOUR_TABLE (username) VALUES(
CONCAT("ADMIN", #id + 1)
);
Query:
SQLFIDDLEExample
INSERT INTO `tbl_user` (
`username`
)
VALUES (
CONCAT('admin',(SELECT MAX(CAST(REPLACE(`username`,'admin','') AS SIGNED INTEGER))+1
FROM (SELECT * FROM tbl_user) t))
);
Result:
| ID | USERNAME |
---------------------
| 1 | admin1 |
| 2 | admin2 |
| (null) | admin3 |
Related
I'm validating following SQL approach from the community where I'm completely updating the user's roles. (Full update of the join table)
User
+----+-------+------+
| id | first | last |
+----+-------+------+
| 1 | John | Doe |
| 2 | Jane | Doe |
+----+-------+------+
Role
+----+----------+
| id | name |
+----+----------+
| 1 | admin |
| 2 | accounts |
| 3 | sales |
+----+----------+
UserRole
+--------+--------+
| userid | roleid |
+--------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
| 2 | 3 |
+--------+--------+
My SQL approach -> first delete all, second insert all records
DELETE FROM UserRole WHERE userid = 1;
INSERT INTO UserRole(userid, roleid) VALUES(1, 2), (1, 3);
Is there a better way? I mean to do this in a single query possibly for these sorts of linking/join tables?
Edit
I think what I should have said to find an efficient SQL operation instead of a single query.
Here's another SQL
DELETE FROM UserRole WHERE user_id = 1 AND role_id NOT IN (2, 3);
INSERT INTO UserRole(user_id, role_id) VALUES(1, 2), (1, 3)
ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), role_id = VALUES(role_id);
If you want to add all roles for all users into the userRoles table, you can delete from userRoles, then recreate table like below:
DECLARE #users TABLE ( userID INT, UserName NVARCHAR(MAX) )
DECLARE #roles TABLE ( roleID INT, RoleName NVARCHAR(MAX) )
DECLARE #userRoles TABLE ( userID INT, roleID INT )
INSERT INTO #users (userID,UserName) VALUES (1,'name1'),(2,'name2'),(3,'name3')
INSERT INTO #roles (roleID,RoleName) VALUES (1,'admin'),(2,'accounts'),(3,'sales')
INSERT INTO #userRoles (userID,roleID)
SELECT U.userID,R.roleID FROM #users U
FULL OUTER JOIN #roles R ON 1=1
ORDER BY userID
SELECT * FROM #userRoles
OUTPUT:
userID roleID
1 1
2 1
3 1
1 2
2 2
3 2
1 3
2 3
3 3
I have a table that uses CHAR as the primary key for customers. I am attempting to load this table into a schema such that the primary key should be an INT.
DROP TABLE IF EXISTS `customers`;
CREATE TABLE `customers` (
`customer_id` char(5) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `customers` VALUES ('99944'),('99946'),('99976'),('A0014'),('A0049'),('A0124'),('C01AH'),('C01AQ'),('C01AW'),('C01AX'),('C01AY'),('C01AZ');
Fiddle
I have attempted variations on select cast(customer_id AS UNSIGNED) FROM customers; but only get back 0s for the non-int rows. How do I cast the non-int rows into a consistent INT result?
The ideal result would look like this:
For customer IDs that are solely integers, leave them alone.
For customer IDs that contain any letter, replace everything in the ID with a unique numerical identifier.
Expected result:
SELECT * FROM Customers;
`customer_id`
-------
99944
99946
99976
13871911
13871912
13871913
13872128
13872229
13872293
13872505
13872512
13872561
GMB did give me a other idea.
Using the HEX() and CONV(.., 16, 10) to convert from hexadecimals into decimales
Query
SELECT
customers.customer_id
, CASE
WHEN (customers.customer_id >> 0) > 0
THEN customers.customer_id >> 0
ELSE
CONV(HEX(customers.customer_id), 16, 10)
END
AS customer_id_int
FROM
customers;
Result
| customer_id | customer_id_int |
| ----------- | --------------- |
| 99944 | 99944 |
| 99946 | 99946 |
| 99976 | 99976 |
| A0014 | 279981338932 |
| A0049 | 279981339705 |
| A0124 | 279981404724 |
| C01AH | 288571343176 |
| C01AQ | 288571343185 |
| C01AW | 288571343191 |
| C01AX | 288571343192 |
| C01AY | 288571343193 |
| C01AZ | 288571343194 |
p.s
It might be generating a to large int you need to use a BIGINT datatype.
see demo
Updated
A other method to generate smaller int's (UNSIGNED INT) which uses a "SQL number generator", SUBSTRING(), ORD() and GROUP_CONCAT().
Query
SELECT
customers.customer_id
CASE
WHEN customers.customer_id >> 1 > 0
THEN customers.customer_id
ELSE
GROUP_CONCAT(
CASE
WHEN SUBSTRING(customers.customer_id, number_generator.number, 1) NOT BETWEEN 'A' AND 'Z'
THEN SUBSTRING(customers.customer_id, number_generator.number, 1) >> 1
ELSE ORD(SUBSTRING(customers.customer_id, number_generator.number, 1))
END
ORDER BY
number_generator.number ASC
SEPARATOR ''
)
END
) AS customer_id_int
FROM (
SELECT
record_1.number
FROM (
SELECT 1 AS number UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5
) AS record_1
) AS number_generator
CROSS JOIN
customers
GROUP BY
customers.customer_id
ORDER BY
customers.customer_id ASC
Result
| customer_id | customer_id_int |
| ----------- | --------------- |
| 99944 | 99944 |
| 99946 | 99946 |
| 99976 | 99976 |
| A0014 | 650002 |
| A0049 | 650024 |
| A0124 | 650012 |
| C01AH | 67006572 |
| C01AQ | 67006581 |
| C01AW | 67006587 |
| C01AX | 67006588 |
| C01AY | 67006589 |
| C01AZ | 67006590 |
see demo
With Maria DB >= 10.0.5, here is a solution to turn a string primary key to an integer primary key in a predictable manner :
SELECT
customer_id old_id,
CAST(
REGEXP_REPLACE(customer_id, '([^0-9])', ORD('$1'))
AS UNSIGNED
) new_id
FROM customers;
REGEXP_REPLACE() captures non-numeric characters (anywhere in the string) and ORD() turns each of them into its ordinal (numerical) represtation.
Demo on DB Fiddle :
old_id | new_id
:----- | -------:
99944 | 99944
9Z946 | 936946
A9CZ6 | 36936366
A0C14 | 3603614
0ABC0 | 3636360
Using MySQL 8.0 REGEXP_REPLACE:
select cast(REGEXP_REPLACE(customer_id,'[^0-9]','') AS UNSIGNED) FROM customers;
db<>fiddle demo
I'm trying to find out if my values inserted are auto-incrementing correctly or if for any reason one has failed to be inserted, deleted or gone "missing". I've tried several answers from Stackoverflow but they were mainly pointing out autoincrementable int values so they did not help since mine is a VARCHAR value that follows the following sequence:
AA000001
AA000002
...
AA000100
...
AA213978
and so on...
Thanks for your time.
You can declare SQL Vars in Query and calculate the difference in each iteration, as shown in the example below:
Schema
create table MyTable
( ai int auto_increment primary key,
id varchar(100) not null
);
insert MyTable (id) values
('AA000001'),
('AA000002'),
('AA000005'),
('AA000008'),
('AA000009'),
('AA000010');
Query
select id
FROM
(
select
t.id,
SUBSTRING(t.id,3) as s,
CAST(SUBSTRING(t.id,3) AS UNSIGNED) - #lastId as diff,
if( #lastId = 0, 0, CAST(SUBSTRING(t.id,3) AS UNSIGNED) - #lastId) as Difference,
#lastId := CAST(SUBSTRING(t.id,3) AS UNSIGNED) as dummy
from
`MyTable` t,
( select #lastId := 0) SQLVars
order by
t.id
) d
WHERE diff>1;
This is the inside query (not the final result set of the above)
+----------+--------+------+------------+-------+
| id | s | diff | Difference | dummy |
+----------+--------+------+------------+-------+
| AA000001 | 000001 | 1 | 0 | 1 |
| AA000002 | 000002 | 1 | 1 | 2 |
| AA000005 | 000005 | 3 | 3 | 5 |
| AA000008 | 000008 | 3 | 3 | 8 |
| AA000009 | 000009 | 1 | 1 | 9 |
| AA000010 | 000010 | 1 | 1 | 10 |
+----------+--------+------+------------+-------+
Actual Results of Above Query:
+----------+
| id |
+----------+
| AA000005 |
| AA000008 |
+----------+
Here's the SQL Fiddle.
To simply test if there are missing values,
select count(*) <> max(right(col, 6))-min(right(col, 6))+1 || count(*) <> count(distinct col)
I have 3 tables: ak_class, ak_objects, ak_class_object
ak_class:
class_id | class_description | class_name |
1 | some description | some name |
2 | some description | some name |
3 | some description | some name |
ak_objects:
object_id | object_description | object_name |
1 | some description | some name |
2 | some description | some name |
3 | some description | some name |
ak_class_object:
class_object_id | class_id | object_id |
1 | 1 | 1 |
2 | 2 | 2 |
3 | 3 | 3 |
I need to fill in the ak_class_object with a class_id from ak_class table and object_id from ak_objects table.
The question is how can I update (I need to update as there is some wrong data currently) the class_id from the ak_class table with all the ids? I was thinking of using it with JOIN ut I don't know which id to use to Join them as class_id is only to be updated
UPD: I was trying to do it like this, but it didn't work:
DELIMITER $$
DROP PROCEDURE class_object_1$$
CREATE PROCEDURE class_object_1()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE (i < 250000) DO
UPDATE ak_class_object
SET class_id = SELECT DISTINCT class_id from ak_class, object_id = SELECT DISTINCT class_id from ak_objects;
SET i = i + 1;
END WHILE;
END$$
I am writing the generic syntax, change the table names and column name as per your requirements.
update table1 inner join table2
on table1.id = table2.fk_id
set table1.column = table1.columnUpdated
I have a table like this:
+----------------------------+
| id | name | helper |
+----------------------------+
| 1 | user1 | NULL |
| 2 | user1 | NULL |
| 3 | user1 | NULL |
| 4 | user2 | NULL |
| 5 | user2 | NULL |
+----------------------------+
Now I want to update the LAST occurrence of "user1" - how do I do that?
This is my example query right now:
UPDATE Table SET helper = 'bob' WHERE name = 'user1' AND helper IS NULL;
However, this updates all the "user1" Entries.
Thanks in advance.
update t set helper = 'bob' where name = 'user1' order by id desc limit 1;
see it working live in an sqlfiddle
This should work.
UPDATE Table SET helper = 'bob' WHERE id = (SELECT MAX(id) FROM Table WHERE name = 'user1')
Just use MAX(id) to get the last row of 'user1'.