insert/update mysql column based on existing data - mysql

I'm updating an existing table by adding data into an existing column.
I have already have an output of the data to be inserted, but due to the amount of records, i'm looking for the best way to insert this into my table without having to manually write to each line of sql.
Here's my sql (partial) i want to insert into
INSERT INTO `tbl_user_variables_dobRE` (`user_id`, `value`) VALUES
(150, '1959-11-02'),
(151, '1948-04-20'),
(152, '1961-06-18'),
And this is the table i want to insert it into
id | 7
username | guestinvite
password | BLANK
forname | forname
surname | surname
email | guestinvite#test.com
address_id | 286
type_id | 4
dob | 0000-00-00
plusGuest | 0
update | 2016-02-16 11:54:36
created | 2016-04-04 17:03:12
So i want to insert the second item into the 'dob' column where first item = id
Is there anyway to do this programmatically or do i have to write WHERE & OR statements for every line?

You tagged both MySql AND sql-server in your post. The following is assuming you're using SQL Server, but the idea would remain the same in MySQL (just different syntax)...
If I'm understanding correctly, it sounds like you want to do an UPDATE, not an INSERT, being that you're modifying existing rows.
You said that you have an output of the data to be inserted - Insert this into a TEMP table and JOIN it to the table you'd like to update where the id's match.
BEGIN TRANSACTION [Transaction1] -- Do large updates as transactions to avoid data loss
CREATE TABLE #temp ( -- Create temp table
[user_id] int,
[dob] nvarchar(20)
)
INSERT INTO #temp
-- YOUR SELECT GOES HERE
SELECT my_id as [user_id], my_dob as [dob]
UPDATE my_table
SET my_table.dob = t.dob
FROM tbl_user_variables_dobRE my_table
INNER JOIN #temp t ON t.user_id = my_table.id
DROP TABLE #temp
If your data looks good, commit the transaction: (Don't dwell too long, transactions lock table data!)
COMMIT TRANSACTION [Transaction1]
Otherwise:
ROLLBACK TRANSACTION [Transaction1]

The quickest way I can think of doing this is creating a temporary table with the new data that you want to add (you could possibly bulk import it all from say, a CSV file).
The temporary table will just need a couple of columns - one with user_id and the other one dob - you'll be getting rid of it after anyway.
You could then do something like this:
UPDATE tbl_user_variables_dobRE a
JOIN tmp_table b
ON ( a.user_id = b.user_id )
SET a.dob = b.dob
Once you've done that you can DROP your temporary table and be good to go - good luck!
Important
Be super-careful when updating data - it's so easy to mess up your data by forgetting to add a clause. If possible, do this with some test data before trying it with the real production data.

Related

SQL normalized data INSERT WHERE NOT EXISTS ; ON DUPLICATE KEY UPDATE

i am using MySql Workbench version 6.3.9 with mySql 5.6.35.
i have the following tables:
EQUIPMENT
eID | caochID | eName
COACH
coachID | coachName
SQLfiddle prepared http://sqlfiddle.com/#!9/e333d/1
eID is a primary key. there are multiple coachID's in different equipment, so there will be duplicate coachIDs with different equipment, but the eID will be unique as it is a primary key.
REQUIRED
i need to insert a row in the equipment table, if it does not already exist. If it exists, do nothing.
various posts online have pointed me towards two options:
a) INSERT...ON DUPLICATE KEY UPDATE...
b)INSERT...WHERE NOT EXISTS
PROBLEM i have problems with both of these solutions. for the first solution (ON DUPLICATE KEY UPDATE) the query inserts the row as required but does not update the existing row. instead it creates a new entry. for the second solution (WHERE NOT EXISTS) i get an error : SYNTAX ERROR: 'WHERE' (WHERE) is not a valid input at this position.
the sql query doesnt need to make any joins. i listed both tables so that you can see how they are related. the insert query i need will only insert for the equipment table.
You can insert by using a tmp table and ensuring that the same record is not existing from current table. Add limit 1 to ensure only one record is inserted. Below query will not insert since 1 and small ball exists.
INSERT INTO `Equipment` (`c_id`, `eName`)
SELECT * FROM (SELECT '1', 'small ball') tmp
WHERE NOT EXISTS (
SELECT c_id FROM Equipment WHERE `c_id`='1' and `eName` = 'small ball'
) LIMIT 1;
NOT EXISTS
insert into table2 (....) --- all if not columns ... destination
select ....
from table1 t1 --- source of data to check
where not exists (
select 1
from table2 t2
where t2.col = t1.col --- match source and destination table making sure table1 data is not in table2
)

SQL Trigger: New row :tableA to new col in :tableB

I have a database with a couple of tables. I need to add a column in one table after the insertion of a new row in another table.
Table A: id | Type | Category | ShortDesc | LongDesc | Active
Row 1 int(11), varchar, varchar,varchar,varchar,int
Row 2
Row 3
Table B: id | Row1-ShortDesc | Row2-ShortDesc | Row3-ShortDesc
Row 1 int(11), tiny(1), tiny(1), tiny(1) etc...
Row 2
Row 3
When I occasionally add a new row (item) to TableA, I want a new column in TableB. TableA is a long evolving collection. A Row in TableA can not be removed for obvious legacy reasons.
So when I insert a row to TableA I need to have another column inserted/appended into TableB.
Any help would be appreciated.
TIA.
Answer derived from training in SQL
I was finally able to derive and create my trigger solution utilizing a class in SQL Server at MAX TRAINING in CINCINNATI OHIO.
--SQL CODE
-- Create a table called TableA that just holds some data for the trigger
-- This table has a primary Key seeded with 1 and incremented by 1
CREATE TABLE TableA(
id int identity(1,1) PRIMARY KEY,
name varchar(60) NOT NULL,
shortDesc varchar(60) NOT NULL,
longDesc varchar(60) NOT NULL,
bigDesc TEXT NOT NULL
)
GO
-- Create a table TableB that only has a ID column. ID as a primary key seeded with 1, incremented by 1
CREATE TABLE TableB(
id int identity(1,1) PRIMARY KEY
)
GO
-- Just to see the two tables with nothing in it.
select * from TableA
select * from TableB
GO
-- The actual trigger in TableA based upon an insert
CREATE TRIGGER TR_myInserCol
ON TableA
AFTER INSERT
AS
BEGIN
-- Don't count the trigger events
SET NOCOUNT ON;
-- Because we are making strings we declare some variables
DECLARE #newcol as varchar(60);
DECLARE #lastRow as int;
DECLARE #sql as varchar(MAX);
-- Now fill the variables
-- make sure we are looking at the last, freshly inserted row
SET #lastRow = (SELECT COUNT(*) FROM TableA);
-- Make a SELECT statement for the last row
SET #newcol = (SELECT shortDesc FROM TableA WHERE id = #lastRow);
-- Adds a new column in TableB is inserted based on a
-- TableA.shortDesc as the name of the new column.
-- You can use any row data you want but spaces and
-- special characters will require quotes around the field.
SET #sql = ('ALTER TABLE TableB ADD ' + #newcol + ' char(99)');
-- And run the SQL statement as a combined string
exec(#sql);
END;
GO
--Insert a new rows into TableA
--The trigger will fire and add a column in TableB
INSERT INTO TableA
(name,shortDesc,longDesc,bigDesc)
VALUES ('attract','Attraction','Attractions','Places to go see and have
fun');
GO
INSERT INTO TableA
(name,shortDesc,longDesc,bigDesc)
VALUES ('camp','Camp','CAMP GROUND','Great place to sleep next to a creek');
GO
(name,shortDesc,longDesc,bigDesc)
VALUES ('fuel','GasStation','Fueling Depot','Get gas and go');
GO
INSERT INTO TableA
(name,shortDesc,longDesc,bigDesc)
VALUES ('petstore','PetStore','Pet Store','Get a friend');
GO
-- See the newly created rows in TableA and the new Columns created in TableB
select * from TableA
select * from TableB
GO
-- Do not execute unless you want to delete the newly created tables.
-- Use this to delete your tables
-- Clean up your work space so you can make changes and try again.
DROP TABLE TableA;
DROP TABLE TableB;
GO
Thanks again to those that tried to help me out. And yes, I still understand this may not be the best solution but for me this works as I will only insert rows in TableA maybe a couple of times a year and will more than likely max out with less than 300 rows over the next several years as the data I am working with doesn't change that frequently and have a single row to access with a single bit (T/F) allows me to now quickly assign TableB's to locations and people for their search criteria and to generate a nice SQL query string without multiple reads across potentially several pages. Thanks again!
And if someone wants to add or modify what I have done, I'm all ears. It's all about learning and sharing.
Michael

In SQL, is there an alternative way to see if a record is already there before adding it?

I have a MySQL table like this,
id (primary key) | name | scores
and I am reading a large file to insert records into the MySQL table.
New records will be added into this file but the old records are not deleted, so when I read the file, a lot of records are already in the database.
Except to use SELECT COUNT to see if a record is already in the database, is there a best way to check it (to save processing time & database load)?
Or maybe I should just INSERT it directly? (The database will not allow records with duplicate id anyway.)
I usually use update + insert method.
first i will run the update statement. the update query will act like a select query + directly update the data.
update t1 set t1.Name = 'Name', t1.Scores = 99
where t1.Name = 'Name' and t1.Scores = 99
then check if there is a row affected by the above query. if not run the insert statement
if ##RowCount = 0
insert into t1 (Name, Scores) values ('Name',99)
Serch examples for
INSERT IGNORE INTO table
Simple example for this is
INSERT IGNORE INTO `transcripts`
SET `ensembl_transcript_id` = ‘ENSORGT00000000001′,
`transcript_chrom_start` = 12345
`transcript_chrom_end` = 12678;

Mysql if entry exists

Is there a possibility to check if record exists using mysql?
rowName | number
----------------
dog | 1
cat | 2
For example:
If i have a variable $var = 'dog', which already exists in my database, i want the system to add +1 number to the dog row.
On the other hand, when i have, for example, variable $var='fish', which does not exist in my database, i want the system to insert new row 'fish' with number 1.
I am wondering if there is one query alternative to two different queries using php conditions. I assume it would be faster running only one mysql query.
Please see this INSERT ... ON DUPLICATE KEY UPDATE. For example
INSERT INTO table (rowName, `number`) VALUES ('$var', 1)
ON DUPLICATE KEY UPDATE `number` = `number` + 1;
Try this:
// you can check record exists or not
SELECT EXISTS(SELECT rowName FROM table WHERE rowName="$var");
// you can make one query also
INSERT INTO table(`rowName`, `number`) VALUES ("$var", 1)
ON DUPLICATE KEY UPDATE `number` = `number`+ 1;

Mysql: Create inline table within select statement?

Is there a way in MySql to create an inline table to use for join?
Something like:
SELECT LONG [1,2,3] as ID, VARCHAR(1) ['a','b','c'] as CONTENT
that would output
| ID | CONTENT |
| LONG | VARCHAR(1)|
+------+-----------+
| 1 | 'a' |
| 2 | 'b' |
| 3 | 'c' |
and that I could use in a join like this:
SELECT
MyTable.*,
MyInlineTable.CONTENT
FROM
MyTable
JOIN
(SELECT LONG [1,2,3] as ID, VARCHAR(1) ['a','b','c'] as CONTENT MyInlineTable)
ON MyTable.ID = MyInlineTable.ID
I realize that I can do
SELECT 1,'a' UNION SELECT 2,'b' UNION SELECT 3,'c'
But that seems pretty evil
I don't want to do a stored procedure because potentially a,b,c can change at every query and the size of the data as well. Also a stored procedure needs to be saved in the database, and I don't want to have to modify the database just for that.
View is the same thing.
What I am really looking for is something that does SELECT 1,'a' UNION SELECT 2,'b' UNION SELECT 3,'c' with a nicer syntax.
The only ways i can remember now is using UNION or creating a TEMPORARY TABLE and inserting those values into it. Does it suit you?
TEMPORARY_TABLE (tested and it works):
Creation:
CREATE TEMPORARY TABLE MyInlineTable (id LONG, content VARCHAR(1) );
INSERT INTO MyInlineTable VALUES
(1, 'a'),
(2, 'b'),
(3, 'c');
Usage:
SELECT
MyTable.*,
MyInlineTable.CONTENT
FROM
MyTable
JOIN
SELECT * FROM MyInlineTable;
ON MyTable.ID = MyInlineTable.ID
TEMPORARY_TABLES lifetime (reference):
Temporary tables are automatically dropped when they go out of scope, unless they have already been explicitly dropped using DROP TABLE:
.
All other local temporary tables are dropped automatically at the end of the current session.
.
Global temporary tables are automatically dropped when the session that created the table ends and all other tasks have stopped referencing them. The association between a task and a table is maintained only for the life of a single Transact-SQL statement. This means that a global temporary table is dropped at the completion of the last Transact-SQL statement that was actively referencing the table when the creating session ended.`
What I am really looking for is something that does SELECT 1,'a' UNION SELECT 2,'b' UNION SELECT 3,'c' with a nicer syntax.
Yes, it is possible with ROW CONSTRUCTOR introduced in MySQL 8.0.19:
VALUES ROW (1,'a'), ROW(2,'b'), ROW(3,'c')
and with JOIN:
SELECT *
FROM tab
JOIN (VALUES ROW (1,'a'), ROW(2,'b'), ROW(3,'c') ) sub(id, content)
ON tab.id = sub.id;
db<>fiddle demo
Yes. Do with stored procedures or views.