I'm looking for a query in which i can update a field , with certain where clauses which reside in different tables
To make sure that i do not update all fields which represent the id i need another where clause which also checks if a service_name like '%DISK%' exists in table service_members:
However this results in (logically):
ERROR 1093 (HY000): You can't specify target table 'service_members' for update in FROM clause
My best try so far:
My initial query is not stringent enough as it matches an id/hostname , this id is present multiple times:
update service_members
set check_command_data = replace(check_command_data,'80%!90%','90%!95%')
where host_name in (select id from host where host_name like '%server-01%');
Output:
Query OK, 3 rows affected (0.00 sec)
Rows matched: 23 Changed: 3 Warnings: 0
It works of course but will update the 'new value' which matches on the same 'old value'
What i need to realize in one query:
update in table service_members setting new value for field
check_command_data (works)
host_name needs to be a select id from table host where the host_name
is like %something% (works but not stringent enough)
service_name in table service_members needs to be a select like %DISK%
I'm a bit puzzled on how to get this query working in the right way , any advice/suggestions?
Thanks in advance!
Related
I need to INSERT a new row into my TABLE(with unique field 'A'), if it already exists(duplicate field, insert failed) - just return the ID of the existing one.
This code works well:
insert into TABLE set A=1 on duplicate key update id=last_insert_id(id)
But now I have another problem: how do I know if the returning ID belongs to a new (inserted) row or it's just an old one?
Yes, I can do "SELECT id WHERE A=1" beforehand, but it would overcomplicate the program code, require two steps, and just looks ugly. Besides, in future I may want to remove some UNIQUE indexes, then I'll have to rewrite the program as well to change all the 'where' checks. Maybe there is a better solution?
[solved, see my answer]
Found this solution. It works in console, but doesn't work in my program (must be a bug in the client, idk) - so probably it will work fine for everyone (except me, sigh)
Just check the 'affected rows count' - it will be 1 for the new record and 0 for the old one
mysql> INSERT INTO EMAIL set addr="test" ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
Query OK, 1 row affected (0.01 sec)<----- 1 = INSERTed
mysql> select last_insert_id(); //returns 1
mysql> INSERT INTO EMAIL set addr="test" ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
Query OK, 0 rows affected (0.00 sec) <----- 0 = OLD
mysql> select last_insert_id(); //returns 1
UPD: it didn't work for me because my program kept sending the 'CLIENT_FOUND_ROWS ' flag when connecting to mysql. Removed it, now everything is fine!
I have table with three records. There is one filed as auto_increment. The ID's are 1, 2, 3...
When I run query
SELECT LAST_INSERT_ID() FROM myTable
The result is 5, even the last ID is 3. Why?
And what is better to use? LAST_INSERT_ID() or SELECT MAX(ID) FROM myTable?
The LAST_INSERT_ID() function only returns the most recent autoincremented id value for the most recent INSERT operation, to any table, on your MySQL connection.
If you haven't just done an INSERT it returns an unpredictable value. If you do several INSERT queries in a row it returns the id of the most recent one. The ids of the previous ones are lost.
If you use it within a MySQL transaction, the row you just inserted won't be visible to another connection until you commit the transaction. So, it may seem like there's no row matching the returned LAST_INSERT_ID() value if you're stepping through code to debug it.
You don't have to use it within a transaction, because it is a connection-specific value. If you have two connections (two MySQL client programs) inserting stuff, they each have their own distinct value of LAST_INSERT_ID() for the INSERT operations they are doing.
edit If you are trying to create a parent - child relationship, for example name and email addresses, you might try this kind of sequence of MySQL statements.
INSERT INTO user (name) VALUES ('Josef');
SET #userId := LAST_INSERT_ID();
INSERT INTO email (user_id, email) VALUES (#userId, 'josef#example.com');
INSERT INTO email (user_id, email) VALUES (#userId, 'josef#josefsdomain.me');
This uses LAST_INSERT_ID() to get the autoincremented ID from the user row after you insert it. It then makes a copy of that id in #userId, and uses it twice, to insert two rows in the child table. By using more INSERT INTO email requests, you could insert an arbitrary number of child rows for a single parent row.
Pro tip: SELECT MAX(id) FROM table is a bad, bad way to figure out the ID of the most recently inserted row. It's vulnerable to race conditions. So it will work fine until you start scaling up your application, then it will start returning the wrong values at random. That will ruin your weekends.
last_insert_id() has no relation to specific tables. In the same connection, all table share the same.
Below is a demo for it.
Demo:
mysql> create table t1(c1 int primary key auto_increment);
Query OK, 0 rows affected (0.11 sec)
mysql> create table t2(c1 int primary key auto_increment);
Query OK, 0 rows affected (0.06 sec)
mysql> insert into t1 values(null);
Query OK, 1 row affected (0.01 sec)
mysql> insert into t2 values(4);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t2 values(null);
Query OK, 1 row affected (0.02 sec)
mysql> select last_insert_id() from t1;
+------------------+
| last_insert_id() |
+------------------+
| 5 |
+------------------+
1 row in set (0.00 sec)
I don't think this function does what you think it does. It returns the last id inserted on the current connection.
If you compare that to SELECT MAX(ID) this selects the highest ID irrespective of connection, be careful not to get them mixed up or you will get unexpected results.
As for why it is showing 5 its probably because its the last id to be inserted, I believe that this value will remain even if the record is removed, perhaps someone could confirm this.
Table level triggers is what can come to rescue here. e.g. before insert trigger.
maybe you should restart the database connection than reconnected again for fresh data
I'm trying to craft a straight SQL (not stored procedure) query that finds all databases in a MySQL database server with a table whose name matches a pattern and has a certain collation, and then use the list of those database names and table names to get a specific value out of the tables that match the pattern.
For this query:
I do not know the names of the databases on the server (they must be queried)
I do not know the names of the tables in the database that could match (they must be compared against a pattern of %options)
For example, if I have 3 databases:
DB1 with tables:
something
f_options (containing a row where the value for a column called option_name is 'test' and the value for the option_value column is 'y')
DB2 with tables:
something
DB3 with tables:
something_else
zeoptions (containing a row where the value for a column called option_name is 'test' and the value for the option_value column is 'z')
Then I want a query that:
Finds databases with tables who match the collation and naming scheme
Select the values of the rows where the column called option_name has a row whose value is "test" in the column
For example, in the above 3 database tables, it would see Database 1 and 3 have a matching table, and it would return the values 'y' and 'z'
I'm trying to do this without using stored procedures or views (just a simple SQL statement).
So far I've gotten a working system that does 1. By querying the MySQL information_schema table, I can get the names of the databases + matching tables using this:
SELECT s.dbname, s.tablename FROM ( SELECT
`information_schema`.`TABLES`.`TABLE_SCHEMA` dbname ,
`information_schema`.`TABLES`.`TABLE_NAME` tablename FROM
`information_schema`.`TABLES` WHERE `information_schema`.`TABLES`.`TABLE_NAME` LIKE
'%options' AND `information_schema`.`TABLES`.`TABLE_COLLATION` LIKE
'utf8mb4_unicode_ci' ) as s;
Now the problem is figuring out how to write a SELECT statement who uses the above SQL statement as a subquery to populate the FROM
Right now this is what I have (though there's an obvious SQL error in how the FROM statement currently works). If I can solve the FROM statement issue I can finish the rest
SELECT `s.dbname`.`s.tablename`.`option_value` FROM `s.dbname`.`s.tablename`
( SELECT `information_schema`.`TABLES`.`TABLE_SCHEMA` dbname ,
`information_schema`.`TABLES`.`TABLE_NAME` tablename FROM
`information_schema`.`TABLES` WHERE
`information_schema`.`TABLES`.`TABLE_NAME` LIKE '%options' AND
`information_schema`.`TABLES`.`TABLE_COLLATION` LIKE 'utf8mb4_unicode_ci' ) as s
WHERE `s.dbname`.`s.tablename`.`option_name` LIKE 'test';
Which can be simplified to
SELECT `s.dbname`.`s.tablename`.`option_value` FROM `s.dbname`.`s.tablename`
( the working query above ) as s
WHERE `s.dbname`.`s.tablename`.`option_name` LIKE 'test';
Does anyone know how I can fix the
FROM `s.dbname`.`s.tablename` ( SELECT ... ) as s
part?
I want to show the result of rows affected after update, insert, or delete in mysql. I have put
DELETE FROM A WHERE ID='1';
SELECT ROW_COUNT();
With the ROW_COUNT the last statement, but the result show me is 0.
If you want to know number of rows affected by delete query in PHPMYADMIN then by running your query it will show you the result see below screenshot :
As #Flash Thunder said PHPmyadmin does not allow multiple queries sent at once
If you want to see the affected rows then you can also write a script using PHP which will exceute you sql query and returns the number of affected rows
Just to be clear.
phpMyAdmin is written in PHP, and PHP does not allow multiple queries sent at once... if you are sending two queries separately, second query is on new connection, so it has no access to previous query information. That's why SELECT ROW_COUNT(); returns 0.
But by default phpMyAdmin returns affected rows count in information after query. It probably uses mysql(i)_affected_rows() function.
FOUND_ROWS() returns number of tables in database when there was no previous query.
mysql> use hunting;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select found_rows();
+--------------+
| found_rows() |
+--------------+
| 24 |
+--------------+
1 row in set (0.00 sec)
mysql> show tables;
(...)
24 rows in set (0.00 sec)
I'm trying to run a SQL query to update a table if an ID does not exists in another table.
Heres the query:
UPDATE product
SET active = 0
WHERE id NOT IN (SELECT product_id FROM image);
This query works as intended on my local server(running apache/mysql).
But on my dedicated server(also running apache/mysql), it just returns this:
Query OK, 0 rows affected (0.19 sec)
Rows matched: 0 Changed: 0 Warnings: 0
But I know it should effect some rows.
I've double checked everything and yet can't see why the query wont go through correctly.
Is there some kind of setting I'm missing out perhaps?
Kind regards,
Daniel
Do you have some rows where product_id is null? You must filter these out when using NOT IN:
UPDATE product
SET active = 0
WHERE id NOT IN (SELECT product_id FROM image WHERE product_id IS NOT NULL);
The reason is that x NOT IN y can only be false or NULL but never true if y contains a NULL value.
You could also use one of the other approaches to find values that occur in one table but not in another. For example, using EXISTS:
UPDATE product
SET active = 0
WHERE NOT EXISTS (SELECT * FROM image WHERE product_id = product.id);
This approach does not have the same problem with NULL values.