Why does MySql update ignore where clause? - mysql

I'd like to find all rows of a table with unformatted text in a specific column and re-format it. Update seems like the right choice for this but it fails. For example this table:
CREATE TABLE `test` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`));
INSERT INTO `test` (name) VALUES ('jerk'),('cad'),('slouch'),('slime');
Running the following update to add an ! to each name that doesn't contain it (but not names that do) ignores the where clause and always updates:
UPDATE test SET name = CONCAT(name, '!') WHERE LOCATE(name, '!') = 0;
Repeated application of this update keeps adding more ! to the end of name.
What's going on here and how can I do this conditional update?
EDIT: fixed typo WHERELOCATE -> WHERE LOCATE

It looks like your arguments for LOCATE are backwards. It's LOCATE(substr, str).
http://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_locate

Related

Error on INSERT statement: "VALUE is not valid at this position"

VALUE is not valid at this position
The error is on VALUES within the INSERT statement. It states it is not supported within this version. Does that mean i require an update or is my syntax wrong?
create schema Cleudo;
USE CLEUDO;
create table Victim(
Vic_ID INT NOT NULL AUTO_INCREMENT,
Vic_Title VARCHAR(10) NOT NULL,
Vic_Name VARCHAR(30) NOT NULL,
Vic_Room VARCHAR(30) NULL,
Vic_TOD VARCHAR(5) NULL,
Vic_Weapon VARCHAR(30) NULL,
PRIMARY KEY ( VIC_ID )
);
INSERT INTO Victim VALUES ('Miss','Scarlet','Library','10:45','candle-Stick');
When I run your code, I get the following error:
Column count doesn't match value count at row 1
This is happening because you are not giving a value to table Vic_ID (which makes sense, because it is auto-incremented). To avoid the error, you need to enumerate the target columns, like so:
INSERT INTO Victim (Vic_Title, Vic_Name, Vic_Room, Vic_TOD, Vic_Weapon)
VALUES ('Miss','Scarlet','Library','10:45','candle-Stick');
Demo on DB Fiddle
You are getting this error because the number of columns are not the same, so you need to change your query to this:
INSERT INTO Victim(Vic_Title,Vic_Name,Vic_Room,Vic_TOD,Vic_Weapon) VALUES ('Miss','Scarlet','Library','10:45','candle-Stick');
In case you want to specify the Vic_ID value you can try this query below instead:
INSERT INTO Victim VALUES (NULL,'Miss','Scarlet','Library','10:45','candle-Stick')

Can I do an INSERT IGNORE using multiple fields as the IGNORE qualifier in MySQL?

I have a MySQL table that looks like this:
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`company_id` int(8) unsigned NOT NULL,
`term_type` varchar(255) NOT NULL DEFAULT '',
`term` varchar(255) NOT NULL DEFAULT '',
I would like to be able to do this...
INSERT IGNORE INTO table ( company_id, term_type, term )
VALUES( a_company_id, 'a_term_type', 'a_term' )
... but I'd like the insert to be ignored when the same combination of company_id, term_type and term already exists. I am aware that if I have a unique index on a single field when I try to insert a duplicate value, the insert will be ignored. Is there a way to do the combo that I'm attempting? Could I use a multi-column index?
I'm trying to avoid doing a SELECT to check for this combination before every insert. As I'm processing hundreds of millions of rows of data into this table.
Maybe something like this:
ALTER TABLE table ADD UNIQUE (company_id, term_type,term);
If you use the IGNORE keyword, errors that occur while executing the INSERT statement are treated as warnings instead. For example, without IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY value in the table causes a duplicate-key error and the statement is aborted. With IGNORE, the row still is not inserted, but no error is issued.
So if you have a multicolumn primary key - it works.

Using mysql triggers to update fields part of a composite primary key

I'm new to mysql triggers and I'm trying to figure it out how should a trigger be created for the following case.
I have a table with the following structure:
CREATE TABLE `trigger` (
`group` int(3) NOT NULL,
`order` int(3) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`group`,`order`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
This is how the table would look with some sample data:
The trigger that I want to create should make sure that, for each new record added with a given group, the order field is updated with the correct order index.
So, if I were to add a new record with the group 1, the order field will be automatically be updated to the next order which, for the given example would be 4.
The following statements inside a trigger should do the trick.
DECLARE neworder INTEGER;
SELECT max(`order`) + 1 INTO neworder FROM `trigger` WHERE `group` = NEW.`group`;
SET NEW.`order` = neworder;
BTW, it's not a great idea to use reserved words for table or column names.
You might want to reconsider your naming scheme.

Insert if not exists

How to have only 3 rows in the table and only update them?
I have the settings table and at first run there is nothing so I want to insert 3 records like so:
id | label | Value | desc
--------------------------
1 start 10 0
2 middle 24 0
3 end 76 0
After this from PHP script I need to update this settings from one query.
I have researched REPLACE INTO but I end up with duplicate rows in DB.
Here is my current query:
$query_insert=" REPLACE INTO setari (`eticheta`, `valoare`, `disabled`)
VALUES ('mentenanta', '".$mentenanta."', '0'),
('nr_incercari_login', '".$nr_incercari_login."', '0'),
('timp_restrictie_login', '".$timp_restrictie_login."', '0')
";
Any ideas?
Here is the create table statement. Just so you can see in case I'm missing something.
CREATE TABLE `setari` (
`id` int(10) unsigned NOT NULL auto_increment,
`eticheta` varchar(200) NOT NULL,
`valoare` varchar(250) NOT NULL,
`disabled` tinyint(1) unsigned NOT NULL default '0',
`data` datetime default NULL,
`cod` varchar(50) default NULL,
PRIMARY KEY (`eticheta`,`id`,`valoare`),
UNIQUE KEY `id` (`eticheta`,`id`,`valoare`)
) ENGINE=MyISAM
As explained in the manual, need to create a UNIQUE index on (label,value) or (label,value,desc) for REPLACE INTO determine uniqueness.
What you want is to use 'ON DUPLICATE KEY UPDATE' syntax. Read through it for the full details but, essentially you need to have a unique or primary key for one of your fields, then start a normal insert query and add that code (along with what you want to actually update) to the end. The db engine will then try to add the information and when it comes across a duplicate key already inserted, it already knows to just update all the fields you tell it to with the new information.
I simply skip the headache and use a temporary table. Quick and clean.
SQL Server allows you to select into a non-existing temp table by creating it for you. However mysql requires you to first create the temp db and then insert into it.
1.
Create empty temp table.
CREATE TEMPORARY TABLE IF NOT EXISTS insertsetari
SELECT eticheta, valoare, disabled
FROM setari
WHERE 1=0
2.
Insert data into temp table.
INSERT INTO insertsetari
VALUES
('mentenanta', '".$mentenanta."', '0'),
('nr_incercari_login', '".$nr_incercari_login."', '0'),
('timp_restrictie_login', '".$timp_restrictie_login."', '0')
3.
Remove rows in temp table that are already found in target table.
DELETE a FROM insertsetari AS a INNER JOIN setari AS b
WHERE a.eticheta = b.eticheta
AND a.valoare = b.valoare
AND a.disabled = b.disabled
4.
Insert temp table residual rows into target table.
INSERT INTO setari
SELECT * FROM insertsetari
5.
Cleanup temp table.
DELETE insertsetari
Comments:
You should avoid replacing when the
new data and the old data is the
same. Replacing should only be for
situations where there is high
probability for detecting key values
that are the same but the non-key
values are different.
Placing data into a temp table allows
data to be massaged, transformed and modified
easily before inserting into target
table.
Deleting rows from temp table is
faster.
If anything goes wrong, temp table
gives you an additional debugging
stage to find out what went wrong.
Should consider doing it all in a single transaction.

mySQL "REPLACE INTO" : is it having any effect in this case

I'm charged with porting some old code to a new platform and I'm looking at a bit that has me pretty puzzled. I think I'm familiar with what REPLACE INTO does, but this leaves me feeling unsure. The mySQL query is:
REPLACE INTO theTable SET value1 = ?, value2 = ?
My understanding is this only has an effect if those columns are defined as unique. The table definition for theTable looks like this:
CREATE TABLE `theTable` (
`value1` int(11) unsigned DEFAULT NULL,
`value2` int(11) unsigned DEFAULT NULL,
KEY `value1` (`value2`),
KEY `value2` (`value2`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
I've inserted a row that's an exact duplicate of an existing row and had nothing happen ( a new row was inserted, the old row still exists ) ... am I missing something or did the original developer just do something that was completely useless?
From MySQL manual:
REPLACE works exactly like INSERT,
except that if an old row in the table
has the same value as a new row for a
PRIMARY KEY or a UNIQUE index, the old
row is deleted before the new row is
inserted...
... Note that unless the table has a
PRIMARY KEY or UNIQUE index, using a
REPLACE statement makes no sense. It
becomes equivalent to INSERT, because
there is no index to be used to
determine whether a new row duplicates
another.
So you need to add UNIQUE KEY in order for it to work.
Like you said: it will only replace (in fact delete + insert) row, if UNIQUE constraint is in place. In your table there is none.