Need to insert CSV values in MySQL column to another table - mysql

I have a CSV file containing user information:
'Arlington', '1,3,5,7,9'
'StackExchange', '2,3'
And I will need the above information imported like this:
"User" table:
id | name
1 | 'Arlington'
2 | 'StackExchange'
"User groups" table:
id | user_id | group_id
1 | 1 | 1
2 | 1 | 3
3 | 1 | 5
4 | 1 | 7
5 | 1 | 9
6 | 2 | 2
7 | 2 | 3
What's the easiest way to do this? I have imported the data with a temp column holding the CSV values:
id | name | tmp_group_ids
1 | 'Arlington' | '1,3,5,7,9'
2 | 'StackExchange' | '2,3'
I am thinking if I import it this way, I will know exactly what id gets assigned for the user (the id column in the users table is auto_increment), and so I can use that id as user_id for the "user groups" table.
But now how do I get values from tmp_group_ids into the "User groups" table?
Would appreciate any help! Thanks!

the easy way would be a php or perl script.

You can use the MySQL SUBSTRING() function to split the string and insert the different values into the table. You can do this by writing a function or using a stored procedure.

I had recently a similar problem, I used the function SUBSTRING_INDEX(str,delim,count), using "," as delimiter
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring-index
INSERT INTO tableUserGroup (userid, groupid)
SELECT
t1.id
, substring_index(t1.tmp_group_ids,',',2)
, substring_index(t1.tmp_group_ids,',',3)
FROM table1 t1

First, insert the names into the User table - with id autonumber, this will work:
INSERT INTO User
(name)
SELECT DISTINCT
name
FROM TempTable
Then:
--- Create a "numbers" table:
CREATE TABLE num
( i INT PRIMARY KEY
) ;
--- Populate it with numbers:
INSERT INTO num
(i)
VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
Then, you can use FIND_IN_SET() function which is handy for this situation (splitting comma-separated fields), like this:
INSERT INTO User_Groups
(user_id, group_id)
SELECT
u.id AS user_id
, num.i AS group_id
FROM User AS u
JOIN TempTable AS t
ON t.name = u.name
JOIN num
ON FIND_IN_SET(num.i, t.tmp_group_ids) > 0

Related

PDO Deleting entries from table that does not exist in post request data

I have a table which consist of columns person_id, level_id, is_admin
person_id | level_id | is_admin
--------------------------------
1 | 1 | 1
1 | 2 | 0
3 | 2 | 1
In the server side, I have a function that accepts a request data which is an array of objects:
[
{person_id: 5, level_id: 1, is_admin: 1},
{person_id: 1, level_id: 2, is_admin: 0}
]
What I want to achieve is that, delete rows from the table whose values of columns person_id, level_id, is_admin does not exists in the post request data.
For example, the expected output of the delete query:
person_id | level_id | is_admin
--------------------------------
1 | 1 | 1
3 | 2 | 1
Notice that the second row is deleted.
EDIT: You might wonder delete entries that do not exists in post data, yes that's right. because the function meant to insert things in the table and delete existing rows that does not exist in the post data.
My current delete query is:
$delete = "
DELETE FROM pivotTable
WHERE NOT EXISTS (
SELECT * FROM (
SELECT
{$personId} AS person_id,
{$levelId} AS level_id,
{$isAdmin} AS is_admin
) as delTemp
);
";
$this->pdo->exec($delete);
no error, but it seems that it's not deleting the row in the database.
Easiest way to debug this would be to run the query as a SELECT:
SELECT FROM pivotTable
WHERE NOT EXISTS (
SELECT * FROM (
SELECT
{$personId} AS person_id,
{$levelId} AS level_id,
{$isAdmin} AS is_admin
) as delTemp
);
After this you can check if the rows you want to delete are correct.
I would also recommend looking into using WHERE NOT IN
as in:
DELETE FROM pivotTable
WHERE (person_id, level_id, is_admin) NOT IN ((5,1,1), (1,2,0));
Also it seems that you aren't using prepared statements which will lead you to be vulnerable to SQL Injection, I would recommend reading on prepared statements here:
https://phpdelusions.net/pdo

SQL code to call all the columns from a Tb expect one column which can be called using As?

My current code is given below. I wanted to call all the columns from the table using * but the idcastncrew column name should display like castncrewid. In the requirement code, it's not working though, I wish there was a solution for my requirement such as the sample Requirement code.
Current code:-
SELECT idcastncrew AS castncrewid,castncrewname,castncrewtype,castncrewrole,imagelink,vendor,mode FROM subscriber;
Requirement :-
SELECT idcastncrew AS castncrewid, * FROM subscriber;
The closest I think you can get is to have the renamed column twice, once with the new name and once with the old name.
While MySQL does not allow * after an aliased column (causing your second code snippet to give an error), it does allow table.* anywhere...
SELECT idcastncrew AS castncrewid, subscriber.*
FROM subscriber;
To re-iterate; you'll still get a idcastncrew column, but you will ALSO get a castncrewid column.
There is no way to say don't include *this* column when using * in MySQL
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=c69c537e46ad29e3c0c8c03d3ebd1bf7
You can alias columns when you alias the table, example as follows
MariaDB [DEV]> create table xxx (id int, str varchar(20));
MariaDB [DEV]> insert into xxx values (1, 'hi');
MariaDB [DEV]> insert into xxx values (2, 'Hello');
MariaDB [DEV]> insert into xxx values (3, 'World');
MariaDB [DEV]> insert into xxx values (4, 'Goodbye');
MariaDB [DEV]> select a.id as id1, a.* from xxx a order by 1;
+------+------+---------+
| id1 | id | str |
+------+------+---------+
| 1 | 1 | hi |
| 2 | 2 | Hello |
| 3 | 3 | World |
| 4 | 4 | Goodbye |
+------+------+---------+

Moving hex data from a varchar type field to bigint type (mysql)

I am trying to insert data from one table into another, and each table has an 'id' field that should be the same, but is stored different datatype. This 'id' field should represent the same unique value, allowing me to update from one to another.
In one table (the new.table one), the 'id' is stored as datatype varchar(35) and in the old.table it is datatype bigint(20) -- I believe this older table represents the integer version of the hex value stored in the new one. I am trying to update data from the new.table back into the old.table
After searching about this for a while
When I try this simple mysql update query it fails:
INSERT INTO old.table (id, field2)
SELECT CAST(CONV(id,16,10) AS UNSIGNED INTEGER), field2
FROM new.table;
It fails with this error:
Out of range value for column 'id' at row 1
I have also tried a simple
SELECT CAST(CONV(id, 16,10) AS UNSIGNED INTEGER) from new.table;
And the result is all the same integer mostly, but each hex value in new.table is unique. I've google this for two days, and could really use to help to figure out what is wrong. Thanks.
EDIT: Some of the example data from console of output of SELECT ID from new.table:
| 1d2353560110956e1b3e8610a35d903a |
| ec526762556c4f92a3ea4584a7cebfe1.11 |
| 34b8c838c18a4c5690514782b7137468.16 |
| 1233fa2813af44ca9f25bb8cac05b5b5.16 |
| 37f396d9c6e04313b153a34ab1e80304.16 |
The problem id is too high values.
MySQL will return limit-value when overflow happened.
Query 1:
select CONV('FFFFFFFFFFFFFFFF1',16,10)
Results:
| CONV('FFFFFFFFFFFFFFFF1',16,10) |
|---------------------------------|
| 18446744073709551615 |
Query 2:
select CONV('FFFFFFFFFFFFFFFF',16,10)
Results:
| CONV('FFFFFFFFFFFFFFFF',16,10) |
|--------------------------------|
| 18446744073709551615 |
I would suggest you, Implement the logic algorithm for id in your case in a function instead of use CONV function.
EDIT
I would use a variable to make new row number and insert to old table.
CREATE TABLE new(
Id varchar(35)
);
insert into new values ('1d2353560110956e1b3e8610a35d903a');
insert into new values ('ec526762556c4f92a3ea4584a7cebfe1.11');
insert into new values ('34b8c838c18a4c5690514782b7137468.16');
insert into new values ('1233fa2813af44ca9f25bb8cac05b5b5.16');
insert into new values ('37f396d9c6e04313b153a34ab1e80304.16');
CREATE TABLE old(
Id bigint(20),
val varchar(35)
);
INSERT INTO old (id, val)
SELECT rn, id
FROM (
SELECT *,(#Rn:=#Rn +1) rn
FROM new CROSS JOIN (SELECT #Rn:=0) v
) t1
Query 1:
SELECT * FROM old
Results:
| Id | val |
|----|-------------------------------------|
| 1 | 1d2353560110956e1b3e8610a35d903a |
| 2 | ec526762556c4f92a3ea4584a7cebfe1.11 |
| 3 | 34b8c838c18a4c5690514782b7137468.16 |
| 4 | 1233fa2813af44ca9f25bb8cac05b5b5.16 |
| 5 | 37f396d9c6e04313b153a34ab1e80304.16 |

I want split the comma seperate value then insert every value to another table in mysql stored procedure

table users as below
--------------------
portal_id | user_id
1 | 100
1 | 101
1 | 102
1 | 103
---------------------
SELECT group_concat(user_id) as toUserIds FROM users where portal_id=1;
after am getting in toUserIds is 100,101,102,103
after i want insert doc_user_xref table as below(same doc id with different user id )
insert into doc_user_xref(doc_id,user_id)values(5211,100);
insert into doc_user_xref(doc_id,user_id)values(5211,101);
insert into doc_user_xref(doc_id,user_id)values(5211,102);
insert into doc_user_xref(doc_id,user_id)values(5211,103);
In above insert value i need loop or iterator.
Don't use GROUP_CONCAT(), just use INSERT ... SELECT:
INSERT INTO doc_user_xref
(doc_id, user_id)
SELECT 5211, user_id
FROM users
WHERE portal_id = 1

Reorder rows in a MySQL table

I have a table:
+--------+-------------------+-----------+
| ID | Name | Order |
+--------+-------------------+-----------+
| 1 | John | 1 |
| 2 | Mike | 3 |
| 3 | Daniel | 4 |
| 4 | Lisa | 2 |
| 5 | Joe | 5 |
+--------+-------------------+-----------+
The order can be changed by admin hence the order column. On the admin side I have a form with a select box Insert After: to entries to the database. What query should I use to order+1 after the inserted column.
I want to do this in a such way that keeps server load to a minimum because this table has 1200 rows at present. Is this the correct way to save an order of the table or is there a better way?
Any help appreciated
EDIT:
Here's what I want to do, thanks to itsmatt:
want to reorder row number 1 to be after row 1100, you plan to leave 2-1100 the same and then modify 1 to be 1101 and increment 1101-1200
You need to do this in two steps:
UPDATE MyTable
SET `Order` = `Order` + 1
WHERE `Order` > (SELECT `Order`
FROM MyTable
WHERE ID = <insert-after-id>);
...which will shift the order number of every row further down the list than the person you're inserting after.
Then:
INSERT INTO MyTable (Name, `Order`)
VALUES (Name, (SELECT `Order` + 1 FROM MyTable WHERE ID = <insert-after-id>));
To insert the new row (assuming ID is auto increment), with an order number of one more than the person you're inserting after.
Just add the new row in any normal way and let a later SELECT use ORDER BY to sort. 1200 rows is infinitesimally small by MySQL standards. You really don't have to (and don't want to) keep the physical table sorted. Instead, use keys and indexes to access the table in a way that will give you what you want.
you can
insert into tablename (name, `order`)
values( 'name', select `order`+1 from tablename where name='name')
you can also you id=id_val in your inner select.
Hopefully this is what you're after, the question isn't altogether clear.