Insert multiple rows into different tables - mysql

I want to insert multiple rows into different tables in my database. The statements are paired, where the second relies on data (specifically LAST_INSERT_ID()) from the first statement.
This code works, but I wonder if it can be done in a better way?
Is there a way to have it all in one single query?
<?php
mysql_query("
INSERT INTO wp_terms (term_id, name, slug, term_group)
VALUES ('', 'Test 1', 'test-1', '0')
");
mysql_query("
INSERT INTO wp_term_taxonomy (term_taxonomy_id, term_id, taxonomy, description, parent, count)
VALUES ('', LAST_INSERT_ID(), 'mycustomfield', 'Descripton 1', '0', '0')
");
mysql_query("
INSERT INTO wp_terms (term_id, name, slug, term_group)
VALUES ('', 'Test 2', 'test-2', '0')
");
mysql_query("
INSERT INTO wp_term_taxonomy (term_taxonomy_id, term_id, taxonomy, description, parent, count)
VALUES ('', LAST_INSERT_ID(), 'mycustomfield', 'Descripton 2', '0', '0')
");
mysql_query("
INSERT INTO wp_terms (term_id, name, slug, term_group)
VALUES ('', 'Test 3', 'test-3', '0')
");
mysql_query("
INSERT INTO wp_term_taxonomy (term_taxonomy_id, term_id, taxonomy, description, parent, count)
VALUES ('', LAST_INSERT_ID(), 'mycustomfield', 'Descripton 3', '0', '0')
");
mysql_query("
INSERT INTO wp_terms (term_id, name, slug, term_group)
VALUES ('', 'Test 4', 'test-4', '0')
");
mysql_query("
INSERT INTO wp_term_taxonomy (term_taxonomy_id, term_id, taxonomy, description, parent, count)
VALUES ('', LAST_INSERT_ID(), 'mycustomfield', 'Descripton 4', '0', '0')
");
?>

If it is a thing to reduce the call of mysql_query, Yes, There is a way but you have to use the mysqli for this.
The mysqli::multi_query can execute the multiple queries in once.

You also can create an INSERT trigger -
DELIMITER $$
CREATE TRIGGER trigger_wp_terms_insert
AFTER INSERT
ON wp_terms
FOR EACH ROW
BEGIN
INSERT INTO wp_term_taxonomy(term_taxonomy_id, term_id, taxonomy, description, parent, count)
VALUES ('', NEW.term_id, 'mycustomfield', CONCAT('Descripton ', SUBSTRING_INDEX(new.name, ' ', '-1')), '0', '0');
END
$$
DELIMITER ;
Then just add new rows into the wp_terms table using one bulk INSERT statement -
INSERT INTO wp_terms (term_id, name, slug, term_group) VALUES
('', 'Test 1', 'test-1', '0'),
('', 'Test 2', 'test-2', '0'),
('', 'Test 3', 'test-3', '0'),
('', 'Test 4', 'test-4', '0');

In my opinion, using a stored procedure would be one of the best ways to do it:
CREATE DEFINER=`root`#`localhost` PROCEDURE `InsertWpTermAndTaxonomy`
( IN paramWPT_id <<PlaceTheRightDataTypeHere>>
, IN paramWPT_name <<PlaceTheRightDataTypeHere>>
, IN paramWPT_slug <<PlaceTheRightDataTypeHere>>
, IN paramWPT_termgroup <<PlaceTheRightDataTypeHere>>
, IN paramWPTX_id <<PlaceTheRightDataTypeHere>>
, IN paramWPTX_taxonomy <<PlaceTheRightDataTypeHere>>
, IN paramWPTX_description <<PlaceTheRightDataTypeHere>>
, IN paramWPTX_parent <<PlaceTheRightDataTypeHere>>
, IN paramWPTX_count <<PlaceTheRightDataTypeHere>>
BEGIN
INSERT INTO wp_terms (term_id, name, slug, term_group)
VALUES (paramWPT_id, paramWPT_name, paramWPT_slug, paramWPT_termgroup)
INSERT INTO wp_term_taxonomy (term_taxonomy_id, term_id, taxonomy, description, parent, count)
VALUES (paramWPTX_id, LAST_INSERT_ID(), paramWPTX_taxonomy, paramWPTX_description, paramWPTX_parent, paramWPTX_count)
END
Then use code like this (though I choose PDO over MYSQL or MYSQLI):
# using an array which you can populate to contain all the
# necessary parameters...
$term_and_taxonomy_array_values = array('', 'Test 4', 'test-4', '0', '', 'mycustomfield', 'Descripton 4', '0', '0');
$sql = 'CALL InsertWpTermAndTaxonomy (?,?,?,?,?,?,?,?,?)';
$stmt = $pdo->prepare($sql);
foreach($term_and_taxonomy_array_values as $key => $value) {
$stmt->bindValue($key + 1, $value);
}
$stmt->execute();
Hope you can look into PDO, but mysqli should be able to do this as well. I coded the procedure so that it can be flexible enough to take whatever acceptable parameters for both tables, even though it seemed like you have constant 0s and ''s
If you want to further make this dynamic, say for example you can build your array of parameter arrays, then you'll just need one more foreach to wrap it up...

add an additional column to wp_terms, you can name the column as session_key, this is to store an unique value for each insertion, an example of unique value can be current timestamp concat with some WP session value
upon insertion, assign the session_key to an unique value and included into insert statement
combine all the insert into wp_terms into single insert ... values (...,session_key), (..., $session_key)
factor in error handling
after you have insert successfully, you can make use on the unique value you have created at step 2 to insert into wp_term_taxonomy select ... where session_key = $session_key
with this small trick, possibilities hitting an error is quite minimum

Related

Error Code: 1136. Column count doesn't match value count at row 1 in a procedure which will add data in 3 tables?

CREATE PROCEDURE `sp_Add_Game` (IN Game_Name_ip VARCHAR(100),IN Genre_ip ENUM('Controllers', 'Extreme Sports', 'Action & Adventure', 'Racing', 'RPG', 'Baseball', 'Sports', 'Systems', 'Puzzle', 'Fighting', 'Strategy', 'FPS', 'Wrestling', 'Accessories', 'Soccer', 'Other', 'Football', 'Party', 'Arcade', 'Basketball', 'Simulation', 'Music'),
IN Rating_ip ENUM('1', '2', '3', '4', '5'),IN Platform_Name_ip ENUM('N64', 'NES', 'Super Nintendo', 'Gamecube', 'Wii', 'Playstation 1', 'Playstation 2', 'Playstation 3', 'Xbox', 'Xbox 360', 'Sega Genesis', 'Atari 2600', 'Gameboy Color', 'Gameboy Advance'),IN Completeness_Type_ip ENUM('B', 'I', 'C', 'BC', 'BI', 'IC', 'BIC'), IN Condition_ip ENUM('New', 'Mint', 'Very Good', 'Good', 'Acceptable', 'Poor'),
IN Purchase_Date_ip DATE,IN Purchase_Price_ip DECIMAL(4,2))
BEGIN
DECLARE Game_key int;
DECLARE MyCollection_Key int;
DECLARE Platform_Key int;
START TRANSACTION;
INSERT INTO videogame_collection_1.video_game(`Game_Name`, `Genre`, `Rating`) VALUES (Game_Name_ip, Genre_ip,Rating_ip,Rating_ip);
SET Game_key = LAST_INSERT_ID();
INSERT INTO videogame_collection_1.mycollection (`Completeness_Type`, `Condition`, `Purchase_Date`, `Purchase_Price`) VALUES (Completeness_Type_ip, Condition_ip, Purchase_Date_ip, Purchase_Price_ip);
SET MyCollection_Key = LAST_INSERT_ID();
INSERT INTO videogame_collection_1.platform(`Platform_Name`) VALUES (Platform_Name_ip);
SET Platform_Key = LAST_INSERT_ID();
INSERT INTO videogame_collection_1.video_game_platform_mycollection(`MyCollection_Id`, `Game_Id`, `Platform_Id`) VALUES (MyCollection_Key,Game_key,Platform_Key);
COMMIT;
END
I am getting the above error when I try to insert video game addition data from front end to Mysql Database. It will insert the data in 3 different tables. So, how can I implement this?
In this statement you are entering the Rating_ip value twice:
INSERT INTO videogame_collection_1.video_game(`Game_Name`, `Genre`, `Rating`) VALUES (Game_Name_ip, Genre_ip,Rating_ip,Rating_ip);
It should read:
INSERT INTO videogame_collection_1.video_game(`Game_Name`, `Genre`, `Rating`) VALUES (Game_Name_ip, Genre_ip,Rating_ip);
You receive the error because you were trying to insert 4 columns worth of data into an insert statement in which you were only specifying 3 columns.

Right hand side position of substring MySQL

I need to blank SSN's from an audit/log table and we can't alter the application.
The application produces an audit/log into table 'redcap_log_event', column 'sql_log'. This column is simply a long string of SQL used by the application when each command was performed within the app.
This is an example of the sql_log column when you copy and paste it out, the carriage returns are in the string of SQL from the column. The inserts end up in the sql_log column from the application -
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'study_id', '123456789', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'cmr_date', '2015-09-02', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'first_name', 'bnm', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'last_name', 'asdfggh', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'dob', '2015-09-02', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'age_at_cmr', '21', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'social_security_number', '987582154', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'sex', '1', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'ethnicity', '1', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'demographics_abef_complete', '2', NULL);
INSERT INTO redcap_data (project_id, event_id, record, field_name, value, instance) VALUES (6, 21, 'Ashby, zbn', 'participant_id', 'asdfggh, zbn', NULL)
I am wanting to eventually blank out the 9 digit SSN value from within the above data via a trigger on the table but for now i'm struggling to get a substring, regex, locate to work how i need it to - The position of text 'social_security_number' within column sql_log will always be different because of the firstname and lastname inserts before it, so i need to somehow find a varying position on the right side of 'social_security_number'
Any ideas appreciated!
Thanks for the downvotes, friendly community i see. Anyway, this is what i finished with:-
USE `ctsiredcap`;
DROP procedure IF EXISTS `SsnBlankOutInsert`;
DELIMITER $$
USE `ctsiredcap`$$
CREATE PROCEDURE `SsnBlankOutInsert` ()
BEGIN
UPDATE redcap_log_event
SET
sql_log = CONCAT(SUBSTR(sql_log,
1,
LOCATE('social_security_number', sql_log) + 25),
'*********',
SUBSTR(sql_log,
LOCATE('social_security_number', sql_log) + 35)),
data_values = CONCAT(SUBSTR(data_values,
1,
LOCATE('social_security_number', data_values) + 25),
'*********',
SUBSTR(data_values,
LOCATE('social_security_number', data_values) + 35))
WHERE
ts > REPLACE(REPLACE(REPLACE(NOW() - INTERVAL 10 MINUTE,
'-',
''),
':',
''),
' ',
'')
AND LOCATE('social_security_number', sql_log) > 0;
END$$
DELIMITER ;
Not pretty by any means but it seems to be doing the job
Thanks,
Allan

Creating Stored Procedures

Write the DDL script to make a stored procedure that returns data needed to display a grade book screen for a professor. The only input for the stored procedure is a ClassId. Outputs need to include student names and grades for all assignments as well as a calculated overall grade for the class for each student. Provide an example calling this new stored procedure, passing it parameter values of your choice. Include a screenshot of the output.
I am unsure how to write this in stored procedure. I don't really understand what is my parameter. I know my input is ClassID and my outputs are student names and grades. Itried this below but keep getting error.
CREATE DEFINER=`root`#`localhost` PROCEDURE `totalAssignmentGradesbyCourse`(aAssignment dec)
SELECT (ClassID) AVG('Assignment1', 'Assignment2',Assignment 3)
FROM student_classes sc
INNER JOIN LastNames, ClassID
ON sc.student_classes
WHERE Assignment=aAssignment
GROUP BY Assignment;
END
fields for Table student_classes:
INSERT INTO student_classes
VALUES (NULL, 45, 36, '2012-01-01', '90', '100', '80', '90', '3.0');
SELECT * FROM student_classes;
INSERT INTO student_classes
VALUES (NULL, 46, 37, '2012-05-01', '60', '70', '80', '90', '2.7');
SELECT * FROM student_classes;
INSERT INTO student_classes
VALUES (NULL, 47, 38, '2012-08-01', '100', '100', '100', '95', '4.0');
SELECT * FROM student_classes;
INSERT INTO student_classes
VALUES (NULL, 48, 39, '2012-01-01', '85', '90', '80', '92', '3.5');
SELECT * FROM student_classes;
student_classes Table Columns:StudentClassID, StudentID, ClassID, StartDate, Assignment1, Assignment2, Assignment3,Assignment4, ClassGPA.
I'm confused.

Get the other field value in case of NULL

CREATE TABLE itemmast (
cid INTEGER,
description varchar(30),
defaultprice DOUBLE);
INSERT INTO itemmast VALUES (1, 'Item 1', '0');
INSERT INTO itemmast VALUES (2, 'Item 2', '8');
INSERT INTO itemmast VALUES (3, 'Item 3', '5.5');
INSERT INTO itemmast VALUES (4, 'Item 4', '0');
INSERT INTO itemmast VALUES (5, 'Item 5', '59');
CREATE TABLE specialprice (
cid INTEGER,
username varchar(30),
newprice DOUBLE);
INSERT INTO specialprice VALUES (4, 'UserS', '10');
INSERT INTO specialprice VALUES (2, 'UserX', '115');
I want to get the value of [newprice] for specific user just in case its in the [specialprice] table, otherwise get the [defaultprice] from the [itemmast] table
So far I have this but not working as expected.
SELECT itemmast.*,newprice,
CASE specialprice.newprice
WHEN NULL
THEN itemmast.defaultprice
ELSE
specialprice.newprice
END AS itemprice
FROM itemmast
LEFT JOIN specialprice ON specialprice.cid = itemmast.cid
where itemmast.cid = '1' and username= 'UserS'
Change your CASE statement into
CASE WHEN specialprice.cid IS NULL
THEN itemmast.defaultprice
ELSE specialprice.newprice
END as RealPrice
SQLFiddle Demo
Or alternatively use COALESCE
COALESCE(specialprice.newprice, itemmast.defaultprice)
SQLFiddle Demo
Why not rather us IFNULL
•IFNULL(expr1,expr2)
If expr1 is not NULL, IFNULL() returns expr1; otherwise it returns
expr2. IFNULL() returns a numeric or string value, depending on the
context in which it is used.
mysql> SELECT IFNULL(1,0);
-> 1
mysql> SELECT IFNULL(NULL,10);
-> 10
mysql> SELECT IFNULL(1/0,10);
-> 10
mysql> SELECT IFNULL(1/0,'yes');
-> 'yes'
So in your example, something like
SELECT itemmast.*,
newprice,
IFNULL(specialprice.newprice, itemmast.defaultprice) itemprice
FROM itemmast LEFT JOIN
specialprice ON specialprice.cid = itemmast.cid
For a more generic approach, use IF(,,):
IF (specialprice.newprice IS NULL, specialprice.defaultprice, specialprice.newprice)
reference: http://dev.mysql.com/doc/refman/5.1/en/control-flow-functions.html#function_if
The other answers are OK, but the reason your SQL is not working is that null is never equal to anything, not even null, and your case statement is comparing the value of specialprice.newprice with null which will never be true.
The only test that is true for null is the special is null test, so you must use that:
case when specialprice.newprice is null ... else ... end
or use a built-in funciton:
select ifnull(specialprice.newprice, itemmast.defaultprice) ...

How to execute 2 or more Hardcoded Insert Statements in MySQL

Does anybody have an idea how to execute the following code in MySQL:
INSERT INTO DLAccountingSystem.tblUserType
(UserTypeName, PermissionXML, LastEditUser, LastEditDate)
VALUES
('Admin', '', 'Admin User', CURDATE());
INSERT INTO DLAccountingSystem.tblUserType
(UserTypeName, PermissionXML, LastEditUser, LastEditDate)
VALUES
('Accountant', '', 'Admin User', CURDATE());
INSERT INTO DLAccountingSystem.tblUserType
(UserTypeName, PermissionXML, LastEditUser, LastEditDate)
VALUES
('Encoder', '', 'Admin User', CURDATE());
Ref:INSERT Syntax
INSERT statements that use VALUES syntax can insert multiple rows. To do this, include multiple lists of column values, each enclosed within parentheses and separated by commas. Example:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
The values list for each row must be enclosed within parentheses. The following statement is illegal because the number of values in the list does not match the number of column names:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3,4,5,6,7,8,9);
Edit: Simple example of Insert multiple records into MySQL with a single query
INSERT INTO DLAccountingSystem.tblUserType
(UserTypeName, PermissionXML, LastEditUser, LastEditDate)
VALUES
('Admin', '', 'Admin User', CURDATE()),
('Accountant', '', 'Admin User', CURDATE()),
('Encoder', '', 'Admin User', CURDATE());
Following statement will insert three records. Follow the same approach.
INSERTINTO a VALUES (1,23),(2,34),(4,33);