Execute insert query, only if count rows equals x - php

$res = $db->query("SELECT COUNT(*) as cnt FROM table")->fetchAll(PDO::FETCH_ASSOC);
if ( $res[0]['cnt'] == 0 ) {
$db->query("
INSERT INTO table (col)
VALUES
('value1'),
('value2'),
('value3'),
....
");
}
Suppose 2 users requested this code same time,
So, for first user, count will return 0 and INSERT query will executed, but there is possible that while first insert executed, for second user, count return also 0 ? (and in this case second insert query will also executed, what I don't need).
If this is possible, how to prevent this? Using Transactions will help in such cases ?

So, you want to insert only if there are no records in the table. Transactions won't help you.
You can use a WRITE LOCK:
Only the session that holds the lock can access the table. No other session can access it until the lock is released.
https://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
Use the following method:
mysql> LOCK TABLES t1 WRITE;
mysql> SELECT COUNT(*) FROM t1;
mysql> INSERT INTO t1 (col)
VALUES
('value1'),
('value2'),
('value3');
mysql> UNLOCK TABLES;
If another session tries to execute the command LOCK TABLES t1 WRITE;, it will wait until the first session finishes. So COUNT will always return the correct value.

Related

How to insert data in SQL temporary table from stored procedure in one query using PHP and drop table after getting resultset?

I have to execute these queries in PHP to get the result
CREATE TABLE #tempDept(deptid int)
INSERT INTO #tempDept
EXEC sprinter_DeptHier1 22;
# This will create a temporary table and insert the result of stored procedure into the temp table
select *
from sprinter_leave_request slr
where slr.id not in (select lr.leave_request_id
from leave_approver lr
where lr.approver_id = 980)
// get userid from session and userid in (select userid from userinfo
where defaultdeptid in (select deptid from #tempDept)) and slr.userid
<> 980 order by userid;
# This query will get the result from temp table
And after getting the result I have to drop the table before next transition occurs.
Kindly help me out to solve the issue, I have to execute the query as same as in the question.
I tried so but have no luck.

SQL SELECT and UPDATE at the same time

I have a very simple SELECT looking like this:
SELECT path FROM items WHERE id = 17
Now in the table items there is also a column count, which I want to have incremented everytime the above query is executed.
What is the optimal way to do this?
There is no way to do that in same query.
You can do something like this:
START TRANSACTION;
UPDATE ....
SELECT ....
COMMIT;
You need to create a stored procedure and then create an atomic transaction using
START TRANSACTION;
UPDATE items set count = (SELECT MAX(count)+1 from items);
SELECT path FROM items WHERE id = 17;
COMMIT;
try combining the update and select into a single call, the response from the SELECT should be returned
UPDATE items SET count = count + 1; SELECT path FROM items WHERE id = 17

MySQL update query in PHP and get multiple ids returned

I want to perform a mysql UPDATE query and then get an array of ids that were effected in the change.
This is my update query
mysql_query("UPDATE table SET deleted='1' WHERE id='$id' OR foo='$foo' OR bar='$bar'");
I know that I can do something like this to get the created id from an INSERT query
mysql_query("INSERT INTO table (id,foo,bar) VALUES ('$id','$foo','$bar')");
$newid = mysql_insert_id();
I don't think MySQL has anything like the OUTPUT or RETURNING clauses that other databases support. You can get the list of ids by running a select before the update:
create table temp_table ids_to_update as
SELECT id
FROM table
WHERE (deleted <> '1' or deleted is null) and *id='$id' OR foo='$foo' OR bar='$bar');
Note that MySQL doesn't do an update when the value doesn't change. Hence the first condition -- which you may or may not find important.
Then, to ensure integrity (in the event of intervening transactions that change the data), you can do:
update table t join
temp_table tt
on t.id = tt.id
set deleted = '1';
You could also wrap the two queries in a single transaction, but I think using a temp table to store the ids is probably easier.

PHP mysql_query Select fails to return row that was just inserted

I am intermittently seeing a problem when trying to select a row immediately after inserting it in PHP. This issue will only happen once in every 100-1000 occurances. This is using php 4.4, with no option to upgrade / be able to use PDO or mysqli. I was considering using transactions, but both queries execute and would continue to do so even with transactions, but the second query runs and returns empty RS so I doubt that transactions would hatch it.
As an example, take a table with two columns: an auto-increment counter, and a stored value. The value must be unique as well, but joins are made on the counter, not the value. Values can be entered by more than one user at a time, so I cannot simply trust the highest counter to give me the value I just inserted.
data:
data_id int(11) UNIQUE AUTO_INCREMENT NOT NULL
myData varchar(50) UNIQUE NOT NULL
Now each user is able to enter a new $val at any time, and when they enter it, an entry must also be made in the status table.
statuses:
status_id int(11) UNIQUE AUTO_INCREMENT NOT NULL
data_id int(11) NOT NULL
status int(1) NOT NULL
The code I'm using to accomplish this is:
// Get value
$insData = $_GET['VAL'];
// Insert value
$ins = mysql_query( "INSERT INTO data (myData) VALUES ('" . $insData . "')" )
or die(mysql_error());
// Get value's id
$res = mysql_query( "SELECT data_id FROM data WHERE myData='" . $insData . "'" )
or die(mysql_error());
// From here I would insert into the statuses table,
// but the new entry into the data table is sometimes not found!
Once every 100-1000 times the code gets run, the select will execute and return no rows. The data insert will execute correctly. I didn't believe that this was possible because the insert or die forces PHP to wait for a return value so that it would know whether or not to execute the 'or die' portion of the line. Is it possible that PHP has received a return value from the insert command before it has finished executing, thus the select statement immediately following the insert fails to return any rows? And how could this intermittent problem be prevented in the future?
There's not a good explanation for why this occasionally fails, although if your table is MyISAM then I suspect you have some sketchiness creeping into your physical table structures. Otherwise there may be something about the values in your unescaped string that is causing the query not to be able to find what it just inserted.
The correct way to identify the last row you inserted it this:
SELECT LAST_INSERT_ID();
or this:
SELECT ##LAST_INSERT_ID;
These are equivalent, and will always give you the value assigned to the auto-increment column of the last row you inserted -- even if another session has inserted data after you.
Is the data you're trying to INSERT (when you don't get the expected error message) a duplicate record (ie matches a record that's already in TABLE DATA) by chance?
If so, see
MySql Gotchas
select statement always return the last inserted row in php mysql
specifically, quoting from mysqlgatchas:
"...A further idiosyncracy seems to be this behaviour:
CREATE TABLE insert_test2 (
id INT NOT NULL PRIMARY KEY,
txt VARCHAR(32)
);
INSERT INTO insert_test2 VALUES(1, 'foo');
INSERT INTO insert_test2 VALUES(2, 'bar');
Now watch this:
mysql> INSERT INTO insert_test2 VALUES(1, 'bar');
ERROR 1062: Duplicate entry '1' for key 1
Correct behaviour... now watch this:
mysql> INSERT INTO insert_test2 (id, txt) SELECT i.id, i.txt FROM insert_test i
WHERE i.id=1;
Query OK, 0 rows affected (0.00 sec)
Records: 1 Duplicates: 1 Warnings: 0
mysql> SELECT * FROM insert_test2;
+----+------+
| id | txt |
+----+------+
| 1 | foo |
| 2 | bar |
+----+------+
2 rows in set (0.00 sec)
Expected behaviour would be for this statement to fail with the same error as above; instead it appears that the statement was successful, with only the Duplicates: 1 notice indicating the statement was effectively ignored.
Update: in version 4.0.20, and possibly previous versions, this statement returns the expected error message..."

quirky SELECT/INSERT statement works the first and third times but not the second?

I have a statement I'm using in PHP that will pull a number if it exists or, if it doesn't, it will create a row, then pull the number from the created row.
The following code works but as the title says...not the second time. First let me clarify, it works everytime if the row exists. But when a row is created and the number returned, the next time through (again with new variables) will fail but then (using same new variables again) will work correctly the next time. This is true in both php and in sql environments.
SELECT id FROM table1 WHERE authID = 'DOEJON' AND periodID = 55
IF ##ROWCOUNT = 0 INSERT INTO table1 (authID, periodID) VALUES ('DOEJON', 55);
SELECT id FROM table1 WHERE timeID = SCOPE_IDENTITY()
there appears to be some sort of refresh related to the statement - how can I get the desired results every time? thoughts?
Thank you for your kind attention.
Try Below
Declare #ID Int
SELECT #ID = id FROM table1 WHERE authID = 'DOEJON' AND periodID = 55
If (id is null)
Begin
INSERT INTO table1 (authID, periodID) VALUES ('DOEJON', 55);
Set #ID = SCOPE_IDENTITY()
End
Select #ID As ID

Categories