Im trying to do an update with a IF function
IF(SELECT 'FUNCION' FROM tickets
WHERE (FUNCION = COR) AND (tickets.CLIENTE=clientes.CLIENTE))
THEN UPDATE `clientes` SET `ESTADO` = 'I';
I tried this but it seems I have a syntax error.
How can I get this to work?
EDIT: I want to update 'ESTADO' to 'I' if 'FUNCION', from another table, is 'COR' and the fields 'CLIENTE' match each other.
You can use a join operation in an UPDATE statement.
It's not clear to me what COR is a reference to, so I'm going to assume it's supposed to be a string literal, not a reference to a column name.
Here's an example:
UPDATE clientes c
JOIN tickets t
ON t.cliente = c.cliente
AND t.funcion = 'COR'
SET c.estado = 'I'
That says, find all rows in clientes that have a "matching" row in tickets, and set the estado column to 'I' on those rows.
Think about it this way... write a SELECT query first to identify the rows you want to update, and filter out the ones you don't.
SELECT c.* -- please don't use * in code in applications!
, t.funcion
FROM clientes c
JOIN tickets t
ON t.cliente = c.cliente
AND t.funcion = 'COR'
--or--
SELECT c.*
FROM clientes c
WHERE EXISTS ( SELECT 1
FROM tickets t
WHERE t.cliente = c.cliente
AND t.funcion = 'COR'
)
Once you have a SELECT statement working (that retrieves ONLY the rows you want to update), you can convert that into an UPDATE, by replacing SELECT ... FROM with the keyword UPDATE, and add a SET clause before the WHERE clause.
There's also some "tricks" we can play in the expression in the SET, to do some conditional assignment. To leave the column unchanged, assign the current value back to the column.
For example, to replace only NULL values of estado
SET c.estado = IF(c.estado IS NULL,'I',c.estado)
If the boolean expression (first argument in the IF() function) evaluates to TRUE, then return the result of the evaluation of the second argument (in this example 'I'), otherwise, return the current value of the estado column.
That's not how you write a conditional update. Use a where clause:
UPDATE clientes
SET estado='I'
WHERE (funcion = cor) AND (tickets.client=clients.cliente)
This won't work, since you're referring to fields/tables that aren't joined into the query.
Related
In this query:
SELECT *
FROM general_settings AS general_settings
JOIN settings_attribute AS settings_attribute ON settings_attribute.id = general_settings.settings_attribute_id
JOIN user_settings AS user_settings ON general_settings.user_settings_id = user_settings.id
WHERE
(settings_attribute.name = 'AAA' AND brand_settings.AAA <> general_settings.value)
OR
(settings_attribute.name = 'BBB' AND brand_settings.BBB <> general_settings.value)
OR
(settings_attribute.name = 'CCC' AND brand_settings.CCC <> general_settings.value)
;
I want a way using MySQL or Redshift to use settings_attribute.name as column name to avoid writing all the attribute names as a static in the query,
for example like this:
SELECT *
FROM general_settings AS general_settings
JOIN settings_attribute AS settings_attribute ON settings_attribute.id = general_settings.settings_attribute_id
JOIN user_settings AS user_settings ON general_settings.user_settings_id = user_settings.id
WHERE
brand_settings.#settings_attribute.name <> general_settings.value
;
No, this is not possible. In SQL, all identifiers (e.g. column names) must be explicit and fixed in the query at the time it is parsed, so the SQL engine can verify that the columns actually exist before it begins executing. It's not possible for a query to name different columns based on the string values it reads during execution.
What would happen if your settings_attribute.name contained 'XYZ' in some row, but there was no column by that name? It would be an error if you named a column that didn't exist, but in SQL that is checked at the time the query is parsed.
I am trying to update a table called jdwf_orders_main if the value of jaj_jno is present in jdwf_alien_jobs table.
I am trying to do it using IF EXISTS but I can't seem to get the syntax right.
What is wrong with my syntax.
IF ( EXISTS (SELECT * from jdwf_alien_jobs where jaj_jno = '7200000') ,
UPDATE jdwf_orders_main set jom_adv_name = 'IAM OP' where jom_job_no = '7200000',
UPDATE jdwf_orders_main set jom_adv_name = 'IAM Noob' where jom_job_no = '7200000');
MySQL does not support the operation you tried. It provides another way to get the same result: update two or more joined tables in a single UPDATE query.
I cannot test but somethings like this should work:
UPDATE jdwf_orders_main om
LEFT JOIN from jdwf_alien_jobs aj ON om.jom_job_no = aj.jaj_jno
SET om.jom_adv_name = IF(af.jaj_no IS NULL, 'IAM Noob', 'IAM OP')
WHERE om.jom_job_no = '7200000'
How it works
It joins the table jdwf_orders_main (aliased as om) with jdwf_alien_jobs (aliased as aj) on the om.jom_job_no = aj.jaj_jno condition.
The LEFT JOIN ensures all the rows from the left table (om) appear in the result set; if a row does not have a matching row in the right table, a row full of NULLs is used for the fields of the right table.
The WHERE clause filters only the rows that match the condition om.jom_job_no = '7200000' to be modified by the UPDATE statement.
The SET clause updates om.jom_adv_name (i.e. the column jom_adv_name from the jdwf_orders_main table) with the value computed by the IF() function.
The IF() function returns 'IAM Noob' if af.jaj_jno is NULL. This happens when for the row from om does not exist any matching row in af (see the explanation of the LEFT JOIN clause above). Otherwise (when a matching row exists), af.jaj_jno is not NULL and the IF() function returns 'IAM OP'.
I have: something like
UPDATE table
SET field = (SELECT field FROM another_table WHERE id = #id);
Problem: SELECT field FROM another_table WHERE id = #id subquery can return one field or EMPTY SET.
Question: How to handle situation when subquery returns empty set?
Updated:
UPDATE table t
SET field = IF((SELECT field FROM another_table WHERE id = #id) IS NOT NULL, -- select field
(SELECT field FROM another_table WHERE id = #id), -- Problem #1: select field AGAIN!
(SELECT field FROM table WHERE id = t.id) -- Problem #2: try to not change value, so select the current field value!!
);
If function can be useful:
UPDATE table
SET field = if((SELECT field FROM another_table WHERE id = #id) IS NULL,true,false);
You can add the conditional:
WHERE (SELECT COUNT(*) FROM another_table WHERE id = #id) > 0
This will make sure that at least one row exists in another_table with the id. See my SQL Fiddle as an example.
Note: this may not be the most efficient because it does a count on another_table, and if it is greater than 1 it will do another SELECT (two sub-queries). Instead, you can do an INNER JOIN:
UPDATE table
INNER JOIN another_table ON table.id=another_table.id
SET table.field = another_table.field
WHERE another_table.id = #id;
See this SQL Fiddle. The reason why I saved this as a second option, is not all SQL languages can UPDATE with joins (MySQL can). Also, you need some way to relate the tables..in this case I said that the table.id we are updating is equal to another_table.id we are taking the data from.
NOTE The UPDATE statement will modify EVERY row in table and assign the same value to every row; that seems a little unusual.
To answer your question:
If you want to handle the "empty set" by not updating any rows in table, then one way to do this is with a JOIN to an inline view:
UPDATE table t
CROSS
JOIN (SELECT a.field
FROM another_table a
WHERE a.id = #id
LIMIT 1
) s
SET t.field = s.field
Note that if the inline view query (aliased as s) return an "empty set", then no rows in table will be updated, because the JOIN operation will also return an "empty set", meaning there are zero rows to be updated.
Using Mysql Sql, How do I update an a table where the field values in "ON" clause
dont match. The order in old table has a few extra letters. The code runs, but the
quantity does not update. Maybe I could concatenate order??
UPDATE t.filled n JOIN t.open o ON n.item = o.item AND n.order = o.order
SET o.Quantity = o.Quantity + n.Quantity WHERE (SUBSTRING_INDEX(n.order,":",-1) = "CLD" )
Solution was to concat one of the x.order to match the other, thus dropping the
where clause.
Due to a data corruption, we have a database field (Mysql 5) which has been populated with text. Its a custom field in the ExpressionEngine CMS and was not set as numeric only. I need to delete only those records for which this field has been incorrectly populated. It contains a URL instead of an ID e.g. 10937.
I need to run a query / stored procedure which will find only those records which have been incorrectly populated i.e do not contain a numeric ID and delete those records, plus linked records in another table.
I would welcome advice on the best way to do this. I could do it from PHP but was hoping to do it in a stored procedure as this would be a useful skill to learn. This question has details of a function which can test if a field is numeric. But I actually need the opposite.
The query I have which will select the records in question is:
SELECT field_id_58 as 'release_id' , ewt.entry_id FROM exp_weblog_data ewd
LEFT JOIN exp_weblog_titles ewt ON ewt.`entry_id` = ewd.`entry_id`
WHERE ewt.weblog_id = 15
This returns all the cms entry_ids I am dealing with, including the ones I want to delete. The field with the incorrect data is field_id_58. The fact that this field has been incorrectly populated means we now have duplicate records in tables ewt and ewd.
Here's what I have so far:
DELIMITER //
CREATE PROCEDURE `proc_DEL_DUPLICATE_PR`
BEGIN
DECLARE empty INT;
DECLARE result ??? # not sure what data type this should be
DECLARE cur1 CURSOR FOR SELECT field_id_58 as 'release_id' , ewt.entry_id FROM exp_weblog_data ewd
LEFT OUTER JOIN exp_weblog_titles ewt ON ewt.`entry_id` = ewd.`entry_id`
WHERE ewt.weblog_id = 15;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET empty=1;
OPEN cur1;
SET empty =0;
WHILE empty = 0 DO
FETCH cur1 INTO result;
#if the release_id in the result row contains a URL string then delete rows for tables ewt, ewd for that entry_id
END IF;
END WHILE;
CLOSE cur1;
END //
You can use regular expressions to find non-numeric fields. The following query will find any rows for which the specified column's value is non-numeric:
SELECT * FROM table_name WHERE column_name REGEXP '[^0-9].+'
Any rows which have a purely numeric value will not be returned. If your DELETE statement uses the same WHERE clause, that should do it.
To delete the rows that contain non-numeric column values, try this query:
DELETE FROM exp_weblog_titles ewt
INNER JOIN exp_weblog_data ewd ON
ewt.`entry_id` = ewd.`entry_id`
WHERE ewt.weblog_id = 15 AND ewd.field_id_58 REGEXP '[^0-9].+';
DELETE FROM exp_weblog_data ewd WHERE ewd.field_id_58 REGEXP '[^0-9].+';
It first deletes all of the relevant rows from the child table, then deletes the parent table rows. Use at your own risk, obviously.
The SQL actually needed to look like this:
DELETE FROM ewt
USING exp_weblog_titles AS ewt
INNER JOIN exp_weblog_data ewd ON ewt.entry_id = ewd.entry_id
WHERE ewt.weblog_id = 15
AND ewd.field_id_58 REGEXP '[^0-9].+';
DELETE FROM exp_weblog_data ewd WHERE ewd.field_id_58 REGEXP '[^0-9].+';