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.
Related
I need to create a table where I have columns country and city.
If I put the country as 'USA', the city must be 'New York'. How to impose this constraint?
I tried but this affects data in other rows too:
UPDATE table1 SET city = IF(country = "USA", 'New York', '');
Also, if possible the constraint should be added while creating the table.
You can either do with the table definition like this.
CREATE TABLE table_name
(
country varchar(30),
state varchar(30),
CONSTRAINT check_state
CHECK ( state = CASE WHEN country ='usa' THEN 'new york' ELSE '' END )
);
Or you can add constraint using ADD CONSTRAINT after creating the table.
As per #Tim's comment, adding the code for trigger to achieve the same
DELIMITER |
CREATE TRIGGER `update_state`
AFTER INSERT ON `table_name` FOR EACH ROW
BEGIN
SET status = CASE WHEN new.country= 'usa' THEN 'New York' else ''
END;
DELIMITER ;
If we go by the logic of updating the table after each insert into the table, then what out need to do is :
UPDATE table1
SET city="new york"
WHERE country="usa";
Here the WHERE clause will take care that only tuples having country as usa are selected.
One of the best way to have the constraint would be using CHECK, but unfortunately CHECK constraints are ignored by MySQL as explained in a miniscule comment in the docs: CREATE TABLE
The CHECK clause is parsed but ignored by all storage engines.
I want to insert values to a row in my customer table if the Name value I'm providing do not already exist,
After some searching I used this sql query to do it and it does not work :(
IF NOT EXISTS (SELECT Name FROM customer WHERE Name = 'Riyafa')
INSERT INTO customer (`Name`, `Address`, `ContactNo`,`Total_amout`)
VALUES ('Riyafa', 'ABC', '555','1000');
Please instruct me why that is incorrect.
The if statement is only allowed in stored procedures, functions, and triggers. One way you can do this is:
INSERT INTO customer (`Name`, `Address`, `ContactNo`,`Total_amout`)
SELECT name, address, contactno, total_amount
FROM (SELECT 'Riyafa' as name, 'ABC' as address, '555' as contact no, '1000' as total_amount) t
WHERE NOT EXISTS (SELECT 1 FROM customer c WHERE c.name = t.name);
A better approach, however, is to have the database enforce uniqueness on the name. Start by creating a unique index or name:
CREATE UNIQUE INDEX idx_customer_name ON customer(name);
Then use a construct such as on duplicate key update:
INSERT INTO customer (`Name`, `Address`, `ContactNo`,`Total_amout`)
SELECT 'Riyafa' as name, 'ABC' as address, '555' as contact no, '1000' as total_amount
ON DUPLICATE KEY UPDATE Name = VALUES(Name);
The expression ON DUPLICATE KEY UPDATE Name = VALUES(Name) actually doesn't do anything, but it prevents the INSERT from returning an error.
I have one table which I have imported into mysql.
Now I need to create multiple related tables.
So basically I have currently got the following
start transaction;
Insert into Address (AddressLine1, AddressLine2, Town, County, Postcode)
Select Distinct Address_line_1, Address_Line_2, Town, County, Postcode from Import;
set addressLastId = last_insert_id();
INSERT INTO Organisation (Name, AddressID)
SELECT DISTINCT Supplier_Name, addressLastId FROM Import;
commit;
The second part where I use the last_insert_id never increments probably because it gets the last insert.
So I need to workout how i can get the previous id for each row inserted into the address table?
Would i need to have an inner loop within the address insert ?
Cheers
I agree with Tim.
After you've populated Address, then you could just run
INSERT INTO Organisation (Name, AddressID)
SELECT DISTINCT Import.Supplier_Name, Address.id
FROM Import INNER JOIN Address ON (set all the address lines and city etc =, since Im guessing there wasnt an address ID in the original import)
You could use a join for the second insert - join Address and Import, and insert the required fields from each into Organisation.
Getting the last insert ID will only work if you process each record sequentially.
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'm using a third party mysql table (ie I can't change any of its properties) and I have a row that has id (key), name and value.
I want to store unique cache keys into a row with the name cacheKeys.. and this is my sql statement
$query = "INSERT INTO ".$tableName." (name, value) VALUES ('CacheKeys', '".$key."') ON
DUPLICATE KEY UPDATE value = CONCAT_WS (',', $tableName.value, '$key')";
I've already implemented my caching algorithm, so that every time someone adds a cache key, I check to see if it already exists (from the CacheKeys row above), if it does I fetch it from cache.. otherwise I store it.
Problem is it seems that the sql write operation takes time, and it often stores duplicate cacheKeys
ie: currencies,defaultCurrencyId,user19,currency1,currency1,currency1,currency1,currency1
So I need to check to see that I'm not adding a duplicate key into the cacheKeys field.. and I need to do that using SQL (using php, ie regex etc would just be waaaay to expensive).
Try this::
INSERT INTO tb (firstname, lastname) VALUES ('Jack', 'Doe') IF NOT
EXISTS ( SELECT * FROM tb WHERE firstname='Jack' AND lastname='Doe' );