Ive been reading about mysqli multi_query and couldnt find a way to do this (if its possible)
$db->multi_query("SELECT id FROM table WHERE session='1';
UPDATE table SET last_login=NOW() WHERE id=table.id");
It doesnt seem to work. I am trying to use the id of the first query to update the second. is this possible
UPDATE table
SET last_login = NOW()
WHERE id IN (SELECT id
FROM table2
WHERE session = '1')
That will update all your records with session = '1'. Assuming of course that the subquery returns more than one result set, which from what I can see, it will.
This also allows you to drop the multi_query() method, as it's just a single query.
In response to the comment:
According to http://lists.mysql.com/mysql/219882 this doesn't appear to be possible with MySQL. Although I suppose you could go for something like:
$db->multiquery(
"UPDATE table
SET last_login = NOW()
WHERE id IN (SELECT id
FROM table2
WHERE session = '1');
SELECT id
FROM table2
WHERE session = '1';"
);
Which is ugly, performing the same query twice, but should do what you want.
Related
I have an app that vends a 'code' to users through an api. A code belongs to a pool of codes that when a user hits an endpoint, he/she will get a code from this 'pool'. At the moment there is only 1 'pool' of codes where a code can be vended. That idea is best expressed below in the following sql.
<<-SQL
UPDATE codes SET vended_at = NOW()
WHERE id = (
SELECT "codes"."id"
FROM "codes"
INNER JOIN "code_batches" ON "code_batches"."id" = "codes"."code_batch_id"
WHERE "codes"."vended_at" IS NULL
AND "code_batches"."active" = true
ORDER BY "code_batches"."end_at" ASC
FOR UPDATE OF "codes" SKIP LOCKED
LIMIT 1
)
RETURNING *;
SQL
So basically, when the end point is pinged, I am returning a code that is active and its vended_at field is NULL.
Now what I need to do is to build off of this sql so that a user can get a code from this pool or from a second pool. So for example, lets say that if the user couldn't get a code from this pool (we will call it A represented by the above sql), I need to vend a code from another pool (we will call it B).
I looked up the documentation of postgresql and I think what I want to do is to either 1). Use a UNION somehow to combine pools A and B into one megapool to vend a code or if I can't vend a code through pool A, use postgresql's OR clause to select from pool B.
The problem is that I can't seem to be able to use either of these syntaxes. I've tried something along the lines like this, tweaking it with different variations.
<<-SQL
UPDATE codes SET vended_at = NOW()
WHERE id = (
SELECT "codes"."id"
FROM "codes"
INNER JOIN "code_batches" ON "code_batches"."id" = "codes"."code_batch_id"
WHERE "codes"."vended_at" IS NULL
AND "code_batches"."active" = true
ORDER BY "code_batches"."end_at" ASC
FOR UPDATE OF "codes" SKIP LOCKED
LIMIT 1
) UNION (
######## SELECT SOME OTHER STUFF #########
)
RETURNING *;
SQL
or
<<-SQL
UPDATE codes SET vended_at = NOW()
WHERE id = (
SELECT "codes"."id"
FROM "codes"
INNER JOIN "code_batches" ON "code_batches"."id" = "codes"."code_batch_id"
WHERE "codes"."vended_at" IS NULL
AND "code_batches"."active" = true
ORDER BY "code_batches"."end_at" ASC
FOR UPDATE OF "codes" SKIP LOCKED
LIMIT 1
) OR (
######## SELECT SOME OTHER STUFF USING OR #########
)
RETURNING *;
SQL
So far the syntax is off and I'm starting to wonder if I can even use this approach for what I'm trying to do. I can't determine if my approach is wrong or if maybe I am using UNION, OR, and SUB-SELECTS wrong. Does anyone have any advice I can try to accomplish my goal? Thank you.
####### EDIT ########
To illustrate and make the concept even easier, I essentially want to do this.
<<-SQL
UPDATE codes SET vended_at = NOW()
WHERE id = (
CRITERIA 1
)
OR/UNION
(
CRITERIA 2
)
RETURNING *;
SQL
Use one table to store both pools.
Add a pool_number column to the codes table to indicate which pool the code is in, then just add
ORDER BY pool_number
to your existing query.
I have simple query that takes some results from User model.
Query 1:
SELECT users.id, users.name, company_id, updated_at
FROM "users"
WHERE (TRIM(telephone) = '8973847' AND company_id = 90)
LIMIT 20 OFFSET 0;
Result:
Then I have done some update on the customer 341683 and again I run the same query that time the result shows different, means the last updated shows first. So postgres is taking the last updated by default or any other things happens here?
Without an order by clause, the database is free to return rows in any order, and will usually just return them in whichever way is fastest. It stands to reason the row you recently updated will be in some cache, and thus returned first.
If you need to rely on the order of the returned rows, you need to explicitly state it, e.g.:
SELECT users.id, users.name, company_id, updated_at
FROM "users"
WHERE (TRIM(telephone) = '8973847' AND company_id = 90)
ORDER BY id -- Here!
LIMIT 20 OFFSET 0
I'm trying to combine two steps into a single query. I'm trying to remove rows from one table with a particular store ID, and then deactivate employees on another table if they no longer have any matching rows in the first table. Here's what I've got:
UPDATE business.employee
SET active = FALSE
WHERE employee_id IN
(SELECT employee_id FROM (DELETE FROM business.employeeStore
WHERE store_id = 1000
RETURNING employee_id) Deleted
LEFT JOIN business.employeeStore EmployeeStore
ON Deleted.employee_id = EmployeeStore.employee_id
WHERE EmployeeStore.store_id IS NULL)
Logically, I think what I've written is sound, but syntactically, it's not quite there. It seems like this should be possible, since the DELETE FROM subquery is returning a single column table of results, and that subquery works fine by itself. But it tells me there is a syntax error at or near FROM. Even if I don't include the UPDATE portion of the query, and just do the interior SELECT part, it gives me the same error.
UPDATE: I tried using a WITH command to get around the syntax problem as follows:
WITH Deleted AS (DELETE FROM business.employeeStore
WHERE store_id = 1000
RETURNING employee_id)
UPDATE business.employee
SET active = FALSE
WHERE employee_id IN
(SELECT employee_id FROM Deleted
LEFT JOIN business.employeeStore EmployeeStore
ON Deleted.employee_id = EmployeeStore.employee_id
WHERE EmployeeStore.store_id IS NULL)
This doesn't produce any errors, but after playing around with the code for a while, I've determined that while it does get the results from the WITH part, it doesn't actually do the DELETE until after the UPDATE completes. So the SELECT subquery doesn't return any results.
I finally was able to work out how to do this using the WITH. The main issue was needing to handle the table in its pre-DELETE state. I've kept it all in one query like so:
WITH Deleted AS
(DELETE FROM business.employeeStore
WHERE store_id = 1000
RETURNING employee_id)
UPDATE business.employee
SET active = FALSE
WHERE employee_id IN
(SELECT employee_id FROM Deleted)
AND employee_id NOT IN
(SELECT employee_id FROM Deleted
JOIN business.employeeStore EmployeeStore
ON Deleted.employee_id = EmployeeStore.employee_id
WHERE EmployeeStore.store_id != 1000)
Postgres fails when I use limit with update statement
I want to update just the first record of a table
UPDATE test1 SET name="user101" LIMIT 1;
this fails in postgres as I am using limit;
I can do this
UPDATE test1 SET name="user101"
WHERE ID =(SELECT ID FROM test1 LIMIT 1)
But to use the above sql I should know the column name (ID) and I don't have access to column name in my case.
I need a sql statement that does not require column name but updates only the first record.
Update:
I am using ruby #db.exec(query) to execute query
We pass different sql statements like below to the method which calls #db.exec(query)
update table1 set t1_name = "123" limit 1;
update table2 set something = "xyz" limit 1;
update table3 set som = "abc" limit 1;
now before calling #db.exec(query)
I want to modify the query such that the query won't use limit
In this case I have access to table name, column name that I want to update. But I don't have access to any other column names (ID).
Although I think this approach has a very bad smell (what kind of application sends updates for random rows to the database), you can use the internal ctid column for this which is always available.
UPDATE test1
SET name = 'user101'
WHERE ctid = (SELECT ctid FROM test1 LIMIT 1)
MySQLi not returning first row
$query = mysqli_query($Connection, "SELECT * FROM `counter`");
while($Counter = mysqli_fetch_array($query))
{
$Counter['id'];
}
it starts returning from the second id, I don't see the problem with it. Even without the loop it still returns the second id first
Assuming the results returned do include all of the records in the table (it should) try adding an ORDER BY id clause to your query, the default ordering is ASC I believe.
If the id column is the tables primary key (your question doesn't state the table schema) I would have thought it should be doing this by default but I am not sure about that tbh!
HTH