IF EXISTS MySQL - php

I'm from a mssql background so it's difficult to get used to MySQL.
I have a table called users_settings. Within this table there are three columns; uid, name, value. Uid is a integer and refers to the user that owns that setting, the name is the name of the setting, the value, well, you guessed it, is the value.
What I'm trying to do is update these settings if it already exists, but if it doesn't, insert a new row.
My current query is as such (Note I'm using prepared statements):
IF EXISTS (SELECT * FROM users_settings WHERE name = ? AND uid = ?) THEN
UPDATE users_settings SET value = ? WHERE name = ? AND uid = ?;
ELSE
INSERT INTO users_settings (uid, name, value) VALUES (?, ?, ?);
END IF;
The issue I'm having is that when I attempt to prepare my statement, it returns false, which therefore suggests that the syntax is incorrect. After looking in to this, it looks like it's a SQL syntax error.
Would anybody be able to point me in the relative direction as to what may be occurring here, and where I may have got my syntax incorrect?

IN MySQL, if as a statement can only used in programming blocks -- stored procedures, functions, and triggers (this is not to be confused with if as a function, which can be used in almost any SQL statement).
You can do what you want in MySQL with a single statement, insert . . . on duplicate key update. For this to work, you need a unique index on name and uid:
create unique index users_settings_name_uid on users_settings(name, uid);
And then:
INSERT INTO users_settings (uid, name, value)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE value = VALUES(value);

There are two ways to fulfill your request in MySQL:
If you want to update an existing row or insert a new one if it does not exist then you should use INSERT ... ON DUPLICATE KEY UPDATE:
INSERT INTO users_settings (uid, `name`, `value`)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);
This relies on an unique index that contains the columns uid and name. If it does not already exist, you can create it:
ALTER TABLE users_settings
ADD UNIQUE INDEX uid_name (uid, `name`);
You need it anyway because you want a single entry in the table for each user and setting name.
If you want to insert a row in the table and replace (discard) another one that already exists then you can use REPLACE:
REPLACE INTO users_settings (uid, `name`, `value`)
VALUES (?, ?, ?);
The syntax of REPLACE is similar with the one of INSERT (but it does not support ON DUPLICATE KEY UPDATE for obvious reasons). Internally it does a DELETE followed by an INSERT (it is just a shortcut). It discards the existing row (if any) and insert the new one. It also relies on the presence of the above mentioned index (that you have no matter how you update the values in the table).
For your situation both approaches have the same outcome because there is a single column (value) that is updated or replaced. In other situations only one of them is good.
Choose the one that you feel more appropriate for your workflow and your coding style.

INSERT INTO persona_opcion(nPerCodigo,nOpcCodigo,nPerOpcEstado)
SELECT '$codPer','$idOpc',1
FROM persona_opcion
WHERE NOT EXISTS(
SELECT nPerCodigo,nOpcCodigo,nPerOpcEstado
FROM persona_opcion
WHERE nOpcCodigo='$idOpc'
and nPerCodigo='$codPer'
)
LIMIT 1;
enter link description here

Related

PHP MySQL Insert Query that won't insert if already exists

I've been doing some research and haven't found anything that I've been able to make work, unfortunately, and I think that stems from not understanding the MySQL construct in the examples I've been looking at.
What I'm trying to do is run an insert query, and do a check on values in 3 specific columns to ensure they don't exist, then insert, else do nothing.
My Table is pretty basic: id(int11), user(varchar(45)), label(varchar(255)), agent(varchar(255)), empid(varchar(10)).
My id is my Primary, with Auto increment, and here is my code I currently have that works on inserting, but doesn't have the handling in place for duplicates:
$i = 0;
foreach ($agents as $ag){
$sql = mysql_query("INSERT INTO `pms_users`
(`id`,`user`,`label`,`agent`,`empid`)
VALUES
(NULL, '$user','$group','$labels[$i]','$ag')");
$i ++;
}
The three columns I need to check against are the $user, $group, and $ag.
Add a unique index for (user, label, empid). Then the database won't allow you to create duplicates.
ALTER TABLE pms_users
ADD UNIQUE INDEX (user, label, empid);
If you can only have one row per combination of user, label and agent, you should define them as a unique constraint:
ALTER TABLE pms_users ADD CONSTRAINT pms_users_unq UNIQUE (`user`, `label`, `agent`);
And then let the database do the heavy lifting with an insert-ignore statement:
INSERT IGNORE INTO `pms_users`
(`user`, `label`, `agent`, `empid`)
VALUES ('some_user', 'some_label', 'some_agent', 123)
You can try insert on duplicate key update query.. It checks duplicate keys. If they exist MySQL do update query if not exist MySQL doing insert query.
Sure in your database you should declare unique keys.
Here is MySQL documentation for this case
https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

Check if MySQL entry exists, if it does, overwrite other columns

I have a MySQL table set out as the following
UID | Thing1 | Thing2 | Date
The UID column has been set as unique and is made from the users ID + the date as an integer. I.E 7620150715
What I'd like to do is check to see if the UID exists, if it does, then update columns thing1 and thing2 with the latest information.
If the UID doesn't exist, then create a new row for all the information.
Currently, what works to enter is
$sql = "INSERT INTO things2 (uid, thing1, thing2, date) VALUES (:uid, :thing1,:thing2,:date)";
But this doesn't work after making UID unique.
I've found that the ON DUPLICATE KEY UPDATE statement seems to be what I'm looking for, but all answers appear to be adding +1 to the input, which is not what I want to do.
Some pseudo syntax for what I'm looking for would go like this
$sql = "INSERT INTO things2 (uid, thing1, thing2, date) VALUES (:uid, :thing1,:thing2,:date ON DUPLICATE KEY UPDATE (thing1, thing2) VALUES (:thing1, :thing2)";
What would be the correct syntax?
Your syntax is a little wrong. If the INSERT fails then you code an UPDATE with the standard UPDATE syntax like so.
$sql = "INSERT INTO things2
(uid, thing1, thing2, `date`)
VALUES (:uid, :thing1,:thing2,:date )
ON DUPLICATE KEY
UPDATE things2 SET thing1 = :thing1, thing2 = :thing2, `date` = :date";
Also date is a reserved word so its best to wrap it in backticks.
The easiest/most clear way needs two steps:
First do an INSERT OR IGNORE of just the (new) UID. Don't bother with the values yet, because you will update anyway. Just make sure that table allows this with proper defaults and not too many constraints:
INSERT OR IGNORE INTO things2 (uid) VALUES (:uid)
Then do an UPDATE ... SET a=b WHERE UID=.. to actually update the records:
UPDATE thing1=:thing1, thing2=:thing2 WHERE UID = :uid
(Not tested, and please check because I am more into C++/sqlite than in MySql/php)

On duplicate Key update.. database key?

I have a table (id, name, price, menu_id)
I have a page in which every item's name and price is shown, and the users can edit it.
But when I submit, it creates new rows.
The index is on the primary key. Should it be on something else?
I tried the following:
INSERT INTO gerechten
SET gerecht_naam = :naam, gerecht_prijs = :prijs, menu_id = :menuid
ON DUPLICATE KEY
UPDATE gerecht_naam = :naam, gerecht_prijs = :prijs
your query will transform to an update whenever any unique key crashes in your table. Up to you to decide where this key should be placed on. For example, your query could be:
INSERT INTO `gerechten` (`name`, `price`, `menu_id`)
VALUES (:name, :price, :menuid)
ON DUPLICATE KEY UPDATE
name = :name,
price = :price
with a unique index on name AND menu_id for example. (I believe there can be several times the same name as long as it is in a different menu)
Of course if there are various fields combinations that must be unique this is a problematic situation and maybe you should use a different approach, such as a select ... lock statement to check previous existence of the values being edited.
You need to add a UNIQUE key to the gerech_naam column and/or to the gerech_prijs (you can have two columns define uniqueness of a row).
If you were to implement these unique keys to the table, you have to be aware that you would still have a problem because if you change the name or the price it could possibly insert in the DB because the data you provide doesn't exist in the table.

How do I check if data exists in my SQL table and if it doesn't insert the newer data?

My table is made up of 3 values-
long
short
id
id is an auto increment int value and the rest are text.
My PHP script retrieves the latest version of a program every half an hour and stores it as long in an sql table. What I want is for the php script to check if the value is already in the table(i.e. there are no new versions). If it isn't I want it to insert the new data.
Just to make this clear I am not replacing the value "long". I am merely making a new value of it and 'id' is keeping a record of how many versions there have been.
Use the EXISTS Keyword.
INSERT INTO Table (Col1, Col2, Col3)
Values(?, ?, ?)
WHERE NOT EXISTS (
SELECT Col1 FROM TABLE
WHERE Col1 = ? AND Col2 = ? AND Col3 =?)
You can work out which columns you actually need to test.
You can put a UNIQUE index on the long column and use INSERT IGNORE:
INSERT IGNORE INTO versions (long, short)
VALUES (?, ?)
If the key already exists MySQL will generate a warning (not an error) and will neither insert nor update any rows.

Insert variables and arrays in different database tables using PHP and MySQLi

I'm learning PHP and MySQL and I'm creating a movies website for learning purposes.
I want to insert variables and arrays containing movie info into a database but in different tables.
This is what I have right now:
include('inc/connection.php');
$conn = dbConnect();
// create SQL
$sql = 'INSERT INTO movies (movieid, title, year, runtime, plot)
VALUES(?, ?, ?, ?, ?)';
// initialize prepared statement
$stmt = $conn->stmt_init();
if ($stmt->prepare($sql)) {
// bind parameters and execute statment
$stmt->bind_param('isiis', $movieid, $title, $year, $runtime, $plot);
$stmt->execute();
}
This insert the variables into the movies table.
But I also need to insert (at the same time) the genres of the movie, the actors, languages, etc... they are in arrays and go into different tables (and maybe also in different rows). For example the array containing the genres (Action, Crime, Drama) genres in the genres table, and the actors in the actors table and so on... I then will use many-to-many and one-to-many tables to display the info.
Can someone explain to me how to do this?? I need to connect to the database multiple times?? I need loops? I'm really new to PHP and MySQLi so please try to explain as much as you can.
Thanks.
INSERT supports only one table at a time, so you'll certainly have to execute multiple INSERT statements if you have complex data that goes into multiple tables.
If you've inserted a specific $movieid value to movies then you know what value you need to insert to the rows of the other tables, to satisfy referential integrity (pseudocode follows, not fully functional example):
$movies_sql = 'INSERT INTO movies (movieid, title, year, runtime, plot)
VALUES(?, ?, ?, ?, ?)';
// execute ($movieid, ...)
$actors_sql = 'INSERT INTO movie_actors (movieid, actorid)
VALUES (?, ?)';
foreach ($actorlist as $actorid) {
// execute ($movieid, $actorid)
}
$lang_sql = 'INSERT INTO movie_languages (movieid, language)
VALUES (?, ?)';
foreach ($languagelist as $language) {
// execute ($movieid, $language)
}
If your movies table uses an AUTO_INCREMENT primary key, then you can get the value generated during the first INSERT either by calling $mysqli->insert_id(), or by using the builtin function LAST_INSERT_ID().
$actors_sql = 'INSERT INTO movie_actors (movieid, actorid)
VALUES (LAST_INSERT_ID(), ?)';
foreach ($actorlist as $actorid) {
// execute ($actorid) -- only one param in this INSERT
}
Note that LAST_INSERT_ID() reports the most recent auto-generated value during your current session, so if you insert to another table that uses an auto primary key, the value changes. But the value reported is stable during your sessions; it does not change if another client session is doing inserts concurrently.
You only need one database connection
Yes you do need loops
Use an auto_increment primary key field in each table, and then use $stmt->insert_id() to extract the value after each insert
If you can, use InnoDB on the MySQL server to get transaction support, and then commit relevant updates together, to ensure that your database is consistent if your script drops out mid-way through an update. The more common MyISAM database table format doesn't support transactions.
You don't need to use more than one database connection - in fact that's what you shouldn't do at all, because you couldn't group your inserts into one atomic transaction.
What you should do (abstract) is:
BEGIN;
INSERT INTO Genres...;
INSERT INTO Actors...;
INSERT INTO othertable....;
and so on, for referenced columns/tables.
INSERT INTO Movies....;
COMMIT;
This way you should always have a consistent dataset.
you are probably going after foreign keys - use one ID from the base table to identify other relations in other table (use movieid in other table to identify what movie the other values belong to etc.)

Categories