Finding ID and inserting it into another table - mysql

I have a table with two columns. ID and WORD. I've used the following query to insert several files into this table
LOAD DATA LOCAL INFILE 'c:/xad' IGNORE INTO TABLE words LINES TERMINATED BY '\n' (#col1) set word=#col1;
Now I'd like to find specific values and insert them into another table. I know based on this question that I can do the following
insert into tab2 (id_customers, value)
values ((select id from tab1 where customers='john'), 'alfa');
But I'd like to do this based on the files. For example:
Loop through each line of file xad and pass it's value to a query like the following
insert into othertable (word_id)
values ((select id from firsttable where word='VALUE FROM CURRENT LINE OF FILE'));
I can write a Java app to do this line by line but I figured it'd be faster to make MySQL do the work if possible. Is there a way to make MySQL loop over each line, find the ID, and insert it into othertable?

Plan A: A TRIGGER could be used to conditionally copy the id to another table when encountered in whatever loading process is used (LOAD DATA / INSERT .. SELECT .. / etc).
Plan B: Simply load the table, then copy over the ids that you desire.
Notes:
The syntax for this
insert into tab2 (id_customers, value)
values ((select id from tab1 where customers='john'), 'alfa');
is more like
insert into tab2 (id_customers, value)
SELECT id, 'alpha'
FROM tab1
WHERE customers = 'john'

Related

Insert into multiple tables only if record doesn't exist in primary table

I don't seem to understand IF statements in SQL very well.
I have two tables, one called event_headers and one called event_records. Each event in has a single entry in the event_header table and at least one record in the event_records table.
I'm running a script in c# that reads SQL files that will insert into each table, but I'm running into a problem with duplicates. I can eliminate the duplicates in the event_header table by using INSERT IGNORE. The trouble I have is I want to be able to skip inserting into the event_records table if there is already an entry in the event_header table.
EXAMPLE:
INSERT INTO `event_headers` (`session_id`, [...] ) VALUES ('89131', [...] );
INSERT INTO `event_records` (`event_header_session_id`, [...] )
VALUES
('89131', [...] ),
('89131', [...] ),
('89191', [...] );
(In truth, I have a third table that also has records that get updated, but this illustrates the point).
I want to only run the INSERT statements if the event_headers.session_id does not exist.
You must check does the 1st insertion inserts the row. You may do this, for example, using ROW_COUNT() which returns the amount of rows really altered in previous statement. The only point - you must use INSERT .. SELECT for 2nd insertion because INSERT .. VALUES does not allow WHERE clause:
INSERT IGNORE INTO main_table VALUES (...);
INSERT INTO slave_table
SELECT *
FROM ( SELECT ... UNION ALL SELECT ... ) slave_data;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0668b71ddcdc67180b3ed54acb562931
Both statements must be executed as a batch (in the same connection, without any other statement between them).
Only one row must be inserted into main table.
But stored procedure which checks the presence in main table and inserts only when no such row is preferred.
Instead of just using VALUES, use a select:
INSERT INTO `event_records` (`event_header_session_id`, col_a, col_b, col_c )
SELECT event_header_session_id, col_a, col_b, col_c
FROM (
SELECT NULL event_header_session_id, NULL col_a, NULL col_b, NULL col_c WHERE 0
UNION ALL
VALUES
ROW('89131', 1,2,3 ),
ROW('89131', 2,3,4 ),
ROW('89191', 3,4,5 );
) new_rows
WHERE NOT EXISTS (
SELECT 1
FROM event_headers
WHERE event_headers.session_id=new_rows.event_headers_session_id
);
The SELECT NULL...UNION ALL is the most portable way I know to name the columns of a VALUES table constructor. On mariadb, omit the ROWs.

Create local temporary table (or view) with multiple values entered manually

How can I create a local temporary table or a view and enter multiple values?
I need this table to use as a filter for other tables, selecting only the products in this list. I cannot do it directly with a where because I need to use this filter multiple times. Therefore I wanted to create this table and join it so that the input needs to be entered only once.
Also, I cannot create normal tables because I don't have this kind of rights. only views or local temporary tables work for me.
This works, but I can enter only 1 product code:
CREATE local TEMPORARY TABLE user_input ON COMMIT preserve rows AS
(
SELECT
'ABC' AS product -- enter PRODUCT CODE here
)
I tried this to enter more than one code, but it does not work:
INSERT INTO user_input(product)
VALUES ('ABC','DEF','GHI)
I think you want to insert three rows, each with one column. That looks like:
INSERT INTO user_input (product)
VALUES ('ABC'), ('DEF'), ('GHI');
Each set of parentheses are the values for a different row.
You can also create the table as:
create user_input as
select 'ABC' as product union all
select 'DEF' union all
select 'GHI';
Or in the most recent versions of MySQL:
create table user_input as
values row('ABC'), row('DEF'), row('GHI');
If you can create a view I would then create it filtering the base table
CREATE VIEW MyView AS
Select Col1, Col2
FROM MyTable
WHERE Col1 in ('A','B','C')
Then you can use this view to filter your queries

Best Method For Quick Uploading of MYSQL Data with Normalization?

Here is my situation. I got this imaginary raw csv data set like this and would contain about 1M lines on average. I would get this data set often every 2 weeks.
PROJECT, MD5SUM_VALUE, USAGE_NAME
A,132412341324asdf,Apple
B,13404892340asdf9,Banana
...
I got mysql tables for
PROJECT_TABLE (id, value),
MD5SUM_VALUE (id, value)
USAGE_NAME (id, name)
RECORD_TABLE (id, project_id, MD5SUM_id, USAGE_id)
I have been using scripts to quickly file load the values of PROJECT (using INSERT IGNORE) into PROJECT_TABLE and a similar strategy to do this for MD5SUM_VALUE and USAGE_NAME.
As it stands today, I got about
17,115,235 unique row entries for USAGE_NAME table
3,001,675 unique row entries for MD5SUM_VALUE table
200 unique row entries for PROJECT table
59m+ rows for RECORD_TABLE table
My uploading of the RECORD_TABLE seems slow. I need to do a query to identify the ids (project_id, MD5SUM_id, USAGE_id) and do this 1 million times+ per raw csv file.
Is there a better way to upload the data? Seems like no way to upload this data part quickly? Should I structure differently?
I would create a temporary table and use that to generate/lookup ids and then insert into your record_table. Assuming you have autoincrement ids on project_table, md5sum_table, and usage_name, and unique keys on the non-id columns:
create temporary table record_table_load (
project varchar(255),
project_id int,
md5sum_value varchar(32),
md5sum_id int,
usage_name varchar(255),
usage_id int
);
load data local infile 'foo.csv'
into table record_table_load
fields terminated by ',' enclosed by '"'
lines terminated by '\n'
ignore 1 lines
(project, md5sum_value, usage_name);
insert ignore into project_table (value) select distinct project from record_table_load;
insert ignore into md5sum_table (value) select distinct md5sum_value from record_table_load;
insert ignore into usage_name (name) select distinct usage_name from record_table_load;
update record_table_load join project_table on project_table.value=record_table_load.project set record_table_load.project_id=project_table.id;
update record_table_load join md5sum_table on md5sum_table.value=record_table_load.md5sum_value set record_table_load.md5sum_id=md5sum_table.id;
update record_table_load join usage_name on usage_name.name=record_table_load.usage_name set record_table_load.usage_id=usage_name.id;
insert into record_table (project_id, md5sum_id, usage_id) select project_id, md5sum_id, usage_id from record_table_load;
drop temporary table record_table_load;
If you want to avoid using insert ignore or you don't have unique constraints on those values, do the lookup, then insert of any values not found, then another lookup.

how to check row number while importing data

We have database table 'field_data_body' and we are using 'insert into ... select from' mysql command to insert data into 'field_data_body' from another table.
Table structure:
In our database table, delta column is used to differentiate same record. For example,
In above exmaple, both row has same data except different value of delta.
How can we set delta while inserting data into database table?
I have search in google and some other questions in stack exchange but did not find solutions.
Thanks in advance.
You could use 2 queries for that.
insert into tablename (col1, col2, ..) Values (value1, value2, ..);
insert into tablename (delta) Values (value) where entity_type = 'node';

Duplicate all data in the same table MYSQL

I'm looking for a way I can duplicate all the rows in my database, I tried exporting it and then importing but I get the duplicate key error.
The reason is purely for testing purposes, I just want a load of dummy data in there to test the system I have out.
Is there a direct statement for this? Or is there a way to export all data except ID (or change ID to MAX(ID) + 1 or AUTO INCREMENT)?
You can try this:
INSERT INTO your_table_name(parent_id,priority,text,shortname,weighting,g_or_a,
dept,ksf,day_start,day_end,date_start,date_end,depends_on,is_question,budget,
ccode,responsible,accountable,consulted,informed)
(SELECT parent_id,priority,text,shortname,weighting,g_or_a,dept,ksf,
day_start,day_end,date_start,date_end,depends_on,is_question,budget,ccode,
responsible,accountable,consulted,informed FROM your_table_name);
Firstly, insert one row in the table 'your_table_name'. Replace your_table_name with the actual table name in above code & execute the code repeatedly until it satisfies the required row numbers. I think it should work.
Put 1 record and then run:
insert into mytable select * from mytable
10 times. This will give you 1024 records. Continue until satisfied.
You could use an INSERT and the values would be a SELECT, just don't select the primary key and don't define it in the insert fields.
Imagine a table with 3 fields, the_pk, field_1, field_2
Something like
INSERT INTO the_table(field_1, field_2) (SELECT field_1, field_2 FROM the_table)