I'm copying a row in a table using this statement:
insert into Buyer (
version, creationDate, password, token, username, zip, city, lastname, firstname, preferredLanguage_id, title_id, contactEmail_id, active
) select
version, creationDate, password, token, "loadtest_1#example.com", zip, city, lastname, firstname, preferredLanguage_id, title_id, contactEmail_id, active
from Buyer where username="developer_de#example.com";
Only thing I change is the username/email. Now the number in the new username to be inserted, "loadtest_1#example.com", should increment every time. So the second should be loadtest_2..., loadtest_3 and so on. I don't really care at what number it starts as long as it's continuous, so taking the ID of the newly inserted row or the like would be totally okay.
Extra kudos for ideas on how to actually create a batch of these inserts so I don't have to run it X times.
You are selecting and inserting to same table and only change is username. what I see is you need a UPDATE statement rather like
update Buyer set username = 'loadtest_1#example.com'
where username="developer_de#example.com";
If it's test and you do really want to insert test data saying loadtest_1#example.com .. loadtest_100#example.com then you can use a while loop like
CREATE PROCEDURE usp_inserttestdata(total INT)
AS
BEGIN
DECLARE counter INT;
DECLARE uname varchar(20);
SET counter = 1;
label1: WHILE counter <= total DO
SET uname = concat('loadtest_', counter, '#example.com');
insert into Buyer (
version, creationDate, password, token, username, zip, city, lastname,
firstname, preferredLanguage_id, title_id, contactEmail_id, active)
select version, creationDate, password, token, uname, zip, city, lastname, firstname,
preferredLanguage_id, title_id, contactEmail_id, active
from Buyer where username="developer_de#example.com";
SET counter = counter + 1;
END WHILE label1;
END
Then call the procedure saying
CALL usp_inserttestdata 1000
You can use AFTER Trigger ON INSERT operation to achive your goal. In the body of this trigger update email and set corresponding value depends on auto increment id value.
Related
I have an user table with 19 rows (first row is admin). I need to add more, so I have another database with a table having more than 1.400.000 users.
My table has an "user_id" as primary key, INT(11), no auto-increment. I need to add users starting in row 20, and only "first_name", "last_name" and "email".
My first try:
INSERT INTO mydatabase.users (first_name, last_name, email) SELECT first_name, last_name, email FROM anotherdatabase.users
That gets me a "Field 'user_id' doesn't have a default value".
I understand it is because user_id is primary key and cannot be null. So, again, it is int(11), non auto-increment.
So I want to add 20,21,22,23 and so on, along the other data. I searched a lot for about 5 hours and can´t seem to find anything I can understand.
Thank you in advance.
To get your numbers starting from 20:
INSERT INTO mydatabase.users (user_id, first_name, last_name, email)
SELECT 19+row_number() over (),
first_name,
last_name,
email
FROM anotherdatabase.users
19+row_number() over ()
'row_number()' = Number of current row within its partition (Mysql documentation)
'over ()' - defines a partition without condition; so in fact counts for the entire table
Details for both can be found under MySQL Window Function concepts and syntax
19+ - ...
Alternatively - if the MySQL version < 8.0:
INSERT INTO mydatabase.users (user_id, first_name, last_name, email)
SELECT (select 20+count(*)
from anotherdatabase.users u1 where u1.id < u.id) as id,
first_name,
last_name,
email
FROM anotherdatabase.users u
This does rather assume that you have a user_id on the other table as well.
The inner select just counts how many records are in the original database that have a smaller id than the record that is being returned at that point (and adds 20 to have the numbering start at 20).
And a third option (not depending on the existence of user_id):
INSERT INTO mydatabase.users (user_id, first_name, last_name, email)
SELECT ( #row_num:=#row_num+1 AS user_id,
first_name,
last_name,
email
FROM anotherdatabase.users u,
(SELECT #row_num:=19) var;
I'm not a great fan of this as it involves creation of variables to keep track of the row number.
Write a procedure that use variable. for i < 1400020 , you would need to count the number of rows in anotherdatabase.users then add the figure with 20.
DELIMITER $$
CREATE PROCEDURE insert_test_data()
BEGIN
DECLARE i INT DEFAULT 20;
WHILE i < 1400020 DO
INSERT INTO mydatabase.users (user_id, first_name, last_name, email)
SELECT i,first_name, last_name, email FROM anotherdatabase.users;
SET i = i + 1;
END WHILE;
END$$
DELIMITER ;
CALL insert_test_data();
DROP PROCEDURE insert_test_data;
I found a simpler way, using variables. I still can´t believe it. It worked like a charm
SET #i=19;
INSERT INTO mydatabase.users(user_id, first_name, last_name, email)
SELECT #i:=#i+1,
first_name,
last_name,
email
FROM anotherdatabase.users;
I have two variables
1. inserted_user_id,
2. inserted_address_id
in my MySQL procedure.
I need to use them in insert queries and select queries. Im trying something like
insert into user_new(name, company, email, customer_id) select name,
company, email, inserted_user_id from user_old;
insert into user_address_map(address_id, user_id) select
inserted_user_id,inserted_address_id ;
There two statements are not working. How to use procedure variable's value in the above sql statements?
First make a select to get all the info: (you need to declare these variables first)
SELECT name,
company,
email,
INTO varname, varcompany, varemail
FROM user_old
then use it into insert
INSERT INTO user_new
(name,
company,
email,
customer_id)
VALUES (varname,
varcompany,
varemail,
inserted_user_id);
edit:
First insert the Selected values and get the id of the inserted row
INSERT INTO user_new
(name,
company,
email)
SELECT name,
company,
email
FROM user_old
SET out_param = last_insert_id();
Then update this row with your param
UPDATE user_new
SET customer_id = inserted_user_id
WHERE id = out_param;
Considering the following TSQL:
INSERT INTO Address(Street1, City, State, ZipCode)
SELECT Street1, City, StateCode, ZipCode
FROM Contact
The Address has an identity column that is automatically set. Is there a way to get a list of the identities of Address records newly inserted?
I know there is ##IDENTITY, but that just returns the last identity.
Assuming the identity column is called AddressID, you can:
INSERT INTO dbo.Address(Street1, ...)
OUTPUT inserted.AddressID
SELECT Street1, ...
FROM dbo.Contact;
Or:
DECLARE #NewAddresses TABLE(AddressID INT);
INSERT INTO dbo.Address(Street1, ...)
OUTPUT inserted.AddressID INTO #NewAddresses
SELECT Street1, ...
FROM dbo.Contact;
Keep in mind ##IDENTITY should almost never be used. Even when dealing with single-row inserts, SCOPE_IDENTITY() is much safer. See this answer for more background.
I want to do all the following in ONE QUERY:
Given some data Address, City, State, Zip. I want to see if a User already exists with that data, and if not insert a new record. If so, just update the date modified on it.
SELECT user_id FROM userInfo WHERE Address = '123 Main ST' AND City = 'New York' AND State='NY' AND Zip = '12345'
If count is greater than 0...
UPDATE userInfo SET modifiedDate = '' WHERE user_id = SELECTED user_id
Else If count is 0
INSERT INTO userInfo (Address, City, State, Zip) VALUES ('123 Main ST', 'New York', 'NY', '12345')
I'd like to point out that the Address and City and State and Zip fields are NOT keys of any type, so REPLACE will not work. Plus, there is additional data I'd like to add in a different query if it does exist.
In that case you cannot. REPLACE is used for inserting or updating and it's the only statement that can do both. But it needs unique keys.
If your filter is not a unique key, you cannot know which of the matching rows should be updated, even if you would write separate statements.
If it is a unique key, you should add a unique index on it, and you will be able to use REPLACE.
Long story short: Determine your key and update your indexes.
To have the option of running two different queries, you'll need to use a Stored Procedure. Try this:
CREATE PROCEDURE sp_UpdateIfNotExists()
BEGIN
DECLARE the_user_id INT; /* or whatever your data type is */
SELECT user_id
INTO the_user_id
FROM userInfo
WHERE Address = '123 Main ST' AND City = 'New York' AND State='NY' AND Zip = '12345'
CASE
WHEN the_user_id IS NULL INSERT INTO userInfo (Address, City, State, Zip) VALUES ('123 Main ST', 'New York', 'NY', '12345');
ELSE UPDATE userInfo SET modifiedDate = '' WHERE user_id = the_user_id
END
Then just execute the stored procedure (with CALL sp_UpdateIfNotExists). You could customize this with parameters and so on, I use these in PHP web applications.
Even for the SELECT to be efficient you will need an index on (State, City, Address). For the data consistency the index should apply UNIQUE constraint.
For partial updates of existing rows there is MySQL specific extention: INSERT ... ON DUPLICATE KEY UPDATE
To know the id of the affected existing row you can use the LAST_INSERT_ID(expr) in the UPDATE clause of the INSERT, and then read the value of the usual LAST_INSERT_ID() or its equivalent.
Hello I'm working on a database assignment and I'm stuck on how to do this one stored procedure. Although It works, sort of...
DELIMITER //
CREATE PROCEDURE AddANewCustomer(IN firstName char(20), IN lastName char(20), IN companyName char(45), IN streetAddress char(60), IN city char(30), IN province char(45), IN postalCode char(6), IN phoneNumber int(10))
BEGIN
DECLARE PersonID INT;
SELECT idPerson FROM Persons WHERE Persons.firstName = firstName AND Persons.lastName = lastName INTO PersonID;
IF PersonID IS NULL THEN
INSERT INTO Persons(firstName, lastName, streetAddress, city, province, postalCode, phoneNumber) VALUES (firstName, lastName, streetAddress, City, Province, postalCode, phoneNumber);
SELECT idPerson FROM Persons WHERE firstName = firstName AND lastName = lastName INTO PersonID;
END IF;
INSERT INTO Customers(idCustomer, companyName) VALUES (Last_Insert_ID(), companyName);
END //
DELIMITER ;
Basically I'm working with Super/Sub types. I want to take the information from the user and then update my parent table (Persons) and pass on the remaining information to my child table (Customers). idPerson is the auto-incrementing PK for Persons table, and I want to use that as a PK/FK for the Customers table's id, idCustomer.
If I run the procedure once, it'll spit out an error 'Result consist of more than one row' and only the Parent table gets updated... But if I run it again, it'll update the Child table properly. Which makes me think that the Last_Insert_ID() parameter is null the first time around and the idPerson only gets updated after the procedure is done.
I've researched for a fix all night and now I'm absolutely stumped on how to solve this.
Ouch.
Basically I'm working with Super/Sub
types.
I don't think so, but I could be wrong. Customer usually describes a relationship between two parties, one a buyer and the other a seller.
If I run the procedure once, it'll
spit out an error 'Result consist of
more than one row'
What do you think that means? Does this query return any rows?
SELECT lastname, firstname, count(*)
FROM Persons
GROUP BY lastname, firstname
HAVING count(*) > 1;
You check for a NULL id number,
IF PersonID IS NULL THEN
but you ignore the possibility that your SELECT statement might return 2 or 3 or 42 different id numbers, all for people who have the same first and last name. Is that wise? Phrased another way, do you have a UNIQUE constraint on {firstname, lastname}?
If PersonID is null, you insert a row into Persons, which sets a value that LAST_INSERT_ID() can return. But your second INSERT tries to use LAST_INSERT_ID() without regard to whether a row was previously inserted into Persons.
Finally, you have two slightly different versions of
SELECT idPerson
FROM Persons
WHERE Persons.firstName = firstName
AND Persons.lastName = lastName
INTO PersonID;
I'm pretty sure you need one at most.