In my php code, I have a Mysql query:
SELECT COUNT(*)
to see if the record already exists, then if it doesn't exist I do an:
INSERT INTO <etc>
But if someone hits reload with a second or so, the SELECT COUNT(*) doesn't see the inserted record.
$ssql="SELECT COUNT(*) as counts FROM `points` WHERE `username` LIKE '".$lusername."' AND description LIKE '".$desc."' AND `info` LIKE '".$key."' AND `date` LIKE '".$today."'";
$result = mysql_query($ssql);
$row=mysql_fetch_array($result);
if ($row['counts']==0) // no points for this design before
{
$isql="INSERT INTO `points` (`datetime`,`username`,`ip`,`description`,`points`,`info`, `date`,`uri`) ";
$isql=$isql."VALUES ('".date("Y-m-d H:i:s")."','".$lusername."',";
$isql=$isql."'".$_SERVER['REMOTE_ADDR']."','".$desc."','".$points."',";
$isql=$isql."'".$key."','".$today."','".$_SERVER['REQUEST_URI']."')";
$iresult = mysql_query($isql);
return(true);
}
else
return(false);
I was using MyISAM database type
Instead of running two seperate queries just use REPLACE INTO.
From the documentation:
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.
For example if your key field is id then:
REPLACE INTO my_table SET id = 4 AND other_field = 'foobar'
will insert if there is no record with id 4, or if there is then it will replace the other_field value with foobar.
How to get the next id in mysql to insert it in the table
INSERT INTO payments (date, item, method, payment_code)
VALUES (NOW(), '1 Month', 'paypal', CONCAT("sahf4d2fdd45", id))
You can use
SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'table_name'
AND table_schema = DATABASE( ) ;
or if you do not wish to use information_schema you can use this
SHOW TABLE STATUS LIKE 'table_name'
You can get the next auto-increment value by doing:
SHOW TABLE STATUS FROM tablename LIKE Auto_increment
/*or*/
SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = 'tablename'
Note that you should not use this to alter the table, use an auto_increment column to do that automatically instead.
The problem is that last_insert_id() is retrospective and can thus be guaranteed within the current connection.
This baby is prospective and is therefore not unique per connection and cannot be relied upon.
Only in a single connection database would it work, but single connection databases today have a habit of becoming multiple connection databases tomorrow.
See: SHOW TABLE STATUS
This will return auto increment value for the MySQL database and I didn't check with other databases. Please note that if you are using any other database, the query syntax may be different.
SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'your_table_name'
and table_schema = 'your_database_name';
SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'your_table_name'
and table_schema = database();
The top answer uses PHP MySQL_ for a solution, thought I would share an updated PHP MySQLi_ solution for achieving this. There is no error output in this exmaple!
$db = new mysqli('localhost', 'user', 'pass', 'database');
$sql = "SHOW TABLE STATUS LIKE 'table'";
$result=$db->query($sql);
$row = $result->fetch_assoc();
echo $row['Auto_increment'];
Kicks out the next Auto increment coming up in a table.
In PHP you can try this:
$query = mysql_query("SELECT MAX(id) FROM `your_table_name`");
$results = mysql_fetch_array($query);
$cur_auto_id = $results['MAX(id)'] + 1;
OR
$result = mysql_query("SHOW TABLE STATUS WHERE `Name` = 'your_table_name'");
$data = mysql_fetch_assoc($result);
$next_increment = $data['Auto_increment'];
Use LAST_INSERT_ID() from your SQL query.
Or
You can also use mysql_insert_id() to get it using PHP.
Solution:
CREATE TRIGGER `IdTrigger` BEFORE INSERT ON `payments`
FOR EACH ROW
BEGIN
SELECT AUTO_INCREMENT Into #xId
FROM information_schema.tables
WHERE
Table_SCHEMA ="DataBaseName" AND
table_name = "payments";
SET NEW.`payment_code` = CONCAT("sahf4d2fdd45",#xId);
END;
"DataBaseName" is the name of our Data Base
Simple query would do
SHOW TABLE STATUS LIKE 'table_name'
For MySQL 8 use SHOW CREATE TABLE to retrieve the next autoincrement insert id:
SHOW CREATE TABLE mysql.time_zone
Result:
CREATE TABLE `time_zone` (
`Time_zone_id` int unsigned NOT NULL AUTO_INCREMENT,
`Use_leap_seconds` enum('Y','N') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
PRIMARY KEY (`Time_zone_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1784 DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Time zones'
See the AUTO_INCREMENT=1784 at the last line of returned query.
Compare with the last value inserted:
select max(Time_zone_id) from mysql.time_zone
Result:
+-------------------+
| max(Time_zone_id) |
+-------------------+
| 1783 |
+-------------------+
Tested on MySQL v8.0.20.
SELECT id FROM `table` ORDER BY id DESC LIMIT 1
Although I doubt in its productiveness but it's 100% reliable
You have to connect to MySQL and select a database before you can do this
$table_name = "myTable";
$query = mysql_query("SHOW TABLE STATUS WHERE name='$table_name'");
$row = mysql_fetch_array($query);
$next_inc_value = $row["AUTO_INCREMENT"];
I suggest to rethink what you are doing. I never experienced one single use case where that special knowledge is required. The next id is a very special implementation detail and I wouldn't count on getting it is ACID safe.
Make one simple transaction which updates your inserted row with the last id:
BEGIN;
INSERT INTO payments (date, item, method)
VALUES (NOW(), '1 Month', 'paypal');
UPDATE payments SET payment_code = CONCAT("sahf4d2fdd45", LAST_INSERT_ID())
WHERE id = LAST_INSERT_ID();
COMMIT;
You can't use the ID while inserting, neither do you need it. MySQL does not even know the ID when you are inserting that record. You could just save "sahf4d2fdd45" in the payment_code table and use id and payment_code later on.
If you really need your payment_code to have the ID in it then UPDATE the row after the insert to add the ID.
What do you need the next incremental ID for?
MySQL only allows one auto-increment field per table and it must also be the primary key to guarantee uniqueness.
Note that when you get the next insert ID it may not be available when you use it since the value you have is only within the scope of that transaction. Therefore depending on the load on your database, that value may be already used by the time the next request comes in.
I would suggest that you review your design to ensure that you do not need to know which auto-increment value to assign next
use "mysql_insert_id()". mysql_insert_id() acts on the last performed query, be sure to call mysql_insert_id() immediately after the query that generates the value.
Below are the example of use:
<?php
$link = mysql_connect('localhost', 'username', 'password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');
mysql_query("INSERT INTO mytable VALUES('','value')");
printf("Last inserted record has id %d\n", mysql_insert_id());
?>
I hope above example is useful.
If return no correct AUTO_INCREMENT, try it:
ANALYZE TABLE `my_table`;
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE (TABLE_NAME = 'my_table');
This clear cache for table, in BD
using the answer of ravi404:
CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
RETURNS BIGINT
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE Value BIGINT;
SELECT
AUTO_INCREMENT INTO Value
FROM
information_schema.tables
WHERE
table_name = TableName AND
table_schema = DATABASE();
RETURN Value;
END
using in your insert query, to create a SHA1 Hash. ex.:
INSERT INTO
document (Code, Title, Body)
VALUES (
sha1( getAutoincrementalNextval ('document') ),
'Title',
'Body'
);
Improvement of #ravi404, in case your autoincrement offset IS NOT 1 :
SELECT (`auto_increment`-1) + IFNULL(##auto_increment_offset,1)
FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = your_table_name
AND table_schema = DATABASE( );
(auto_increment-1) : db engine seems to alwaus consider an offset of 1. So you need to ditch this assumption, then add the optional value of ##auto_increment_offset, or default to 1 : IFNULL(##auto_increment_offset,1)
For me it works, and looks simple:
$auto_inc_db = mysql_query("SELECT * FROM my_table_name ORDER BY id ASC ");
while($auto_inc_result = mysql_fetch_array($auto_inc_db))
{
$last_id = $auto_inc_result['id'];
}
$next_id = ($last_id+1);
echo $next_id;//this is the new id, if auto increment is on
SELECT AUTO_INCREMENT AS next_id FROM information_schema.tables WHERE table_name = 'table name' AND table_schema = 'database name of table name'
mysql_insert_id();
That's it :)
I'm trying to obtain the max primary key in the REDES table in order to add one but it's not working. I was also wondering if this would be the best way to do it and if it's secure.
// mysql inserting a new REDES field
//$redes_maxid = mysql_query("SELECT MAX(id_redessociales) AS id FROM REDES");
//$newmaxid = $redes_maxid + 1;
$redes_maxid = mysql_fetch_row(mysql_query("SELECT max(id_redessociales) AS id FROM REDES"));
$newmaxid = $redes_maxid[0] + 1;
mysql_query("INSERT INTO REDES(id_redessociales, facebook, twitter, linkedin, pinterest) VALUES ('$newmaxid', NULL, NULL, NULL, NULL");
Thanks!
What you're doing is very unsafe and wrong.
This is why we have auto increment fields in databases, just set the id field in your table to auto increment then when inserting a new row simply pass in NULL for the id, MySQL it will automatically do this increment for you safely.
here's a link to the documentation
You can get last id by ordering in descending order and limiting 1 row result
replace this line
$redes_maxid = mysql_fetch_row(mysql_query("SELECT max(id_redessociales) AS id FROM REDES"));
with
$redes_maxid = mysql_fetch_row(mysql_query("SELECT id_redessociales AS id FROM REDES order by id_redessociales DESC limit 1"));
exactly what A.B said
But shouldn't you be making the ID's row in the database auto incremented?
you can set it to auto increment and when you insert a record just make the inserted ID NULL, the database will automaticly number it to the last ID+1
if you are ysing mySql then you can use this SQL statement
ALTER TABLE `myTable` CHANGE `id` `id` TINYINT( 3 ) PRIMARY KEY UNSIGNED NOT NULL AUTO_INCREMENT
I am having a few difficulties with mysql and PDO.
I wish to insert a product into the database, however the product table contains foreign keys. Naturally, I will not know the Foreign key ID when inserting. Am I doing this right??? Is there a better way of tackling this problem?
TABLE Products
Id PK AI int
Name Varchar(20)
CategoryId Int FK
TypeId Int FK
TABLE Categories
Id Int PK
Cat varchar(20)
TABLE Types
Id Int PK
Type varchar(20)
$type = 'Gloves';
$category = 'Clothing';
$sql = 'INSERT INTO Products
SET Name = :name, CategoryId = :catId, TypeId = :typeId
WHERE
CategoryId IN (SELECT Id FROM Categories WHERE Cat = :category) AND
TypeId IN (SELECT Id FROM Types WHERE Type = :type)'
$stmt = $db->prepare($sql);
$stmt->execute(array(':name' => 'Pink childrens gloves', ':category' => $category, ':type' => $type));
As mentioned in a comment below: Normally, I would be getting the ID from a select box. I cannot do this because it will be a script executing the query, not a user.
are you sure that this is what you want?
$sql = 'INSERT INTO Products
SET Name = :name
WHERE
CategoryId IN (SELECT Id FROM Categories WHERE Cat = :category) AND
TypeId IN (SELECT Id FROM Types WHERE Type = :type)'
I think you are trying to use UPDATE
$sql = 'UPDATE Products
SET Name = :name
WHERE
CategoryId IN (SELECT Id FROM Categories WHERE Cat = :category) AND
TypeId IN (SELECT Id FROM Types WHERE Type = :type)'
MySQL allows a combination of SELECT + INSERT in a single query:
INSERT INTO tbl_temp2 (fld_id)
SELECT tbl_temp1.fld_order_id
FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
... but I wouldn't care about it. You cannot do proper error checking if you do three different things in a single query.
My advice is that you first validate that there're a category and a type that match the given names. In that step, you can easily get the corresponding IDs, which will let you perform a simple INSERT. Additionally, if you need to insert many products, you can validate first and once.
In addition to #Álvaro G. Vicario's answer, you can also do something like (works in normal sql, I have not tried it with bound variables):
$sql = 'INSERT INTO Products
SET Name = :name,
CategoryId = (SELECT Id FROM Categories WHERE Cat = :category),
TypeId = (SELECT Id FROM Types WHERE Type = :type)';
But I would always check for existing categories and types first, insert where necessary and get the required id's as this will lead to unexpected results if there are no matches in the inner selects.
First of all you need to figure out which is the table that have foreign key data.
Then you need to get all possible values from foreign key table.
Finally you need to build and drop-down list or similar to give ability of select acceptable foreign key.
$q=$db->prepare('SELECT ke.referenced_table_name assoc_table,
ke.referenced_column_name assoc_col FROM
information_schema.KEY_COLUMN_USAGE ke WHERE ke.referenced_table_name IS NOT NULL
AND ke.table_schema=:database AND ke.table_name=:tablename AND ke.column_name=:col');
$q->bindValue(':database','mydatabasename'); //Set your database name here
$q->bindValue(':tablename','Departments'); //Set your table name here
$q->bindValue(':col','City'); //Set the column which foreign key values you want to have here
if($q->execute()) {
$foreingtable=$q->fetch(PDO::FETCH_ASSOC);
$q=$db->prepare('SELECT '.$foreingtable['assoc_col'].' FROM '.$foreingtable['assoc_table']);
if($q->execute())
echo json_encode($q->fetchAll(PDO::FETCH_COLUMN));
}
else {
header('http/1.1 500 Internal Server Error');
print_r($q->errorInfo());
exit;
}
More about this: Get list of possible foreign key values in MySql using PDO
I have a table with the following fields: gallery(picID, picTimeStamp, location).
What I want is that when someone is uploading a new picture to the gallery, the location will get the same value that picID gets (and picID gets its value by auto increment).
I have tried:
"INSERT INTO gallery(picID, picTimeStamp, location) VALUES (null,'.time().',picID)"
but it is not working. I do not get any errors, the location just always has a zero in it.
Thanks!
You should probably be using trigger like this
CREATE TRIGGER trigger_name BEFORE INSERT ON gallery FOR EACH ROW
BEGIN
DECLARE next_id INT;
SET next_id = (SELECT AUTO_INCREMENT FROM gallery WHERE TABLE_NAME='gallery');
SET NEW.location=next_id;
END
edit: Should be after insert trigger instead of before because auto_increment number only gets set after the record is inserted. Sorry bout that!
Your table should be like this:
id | int | primary key/autoincrement
order | int | index
picTimeStamp | timestamp
and then if you want to create a new entry below pass the order number by GET:
function createBelow(){
if(isset($_GET["orders"])){
$orders = $_GET["orders"];
$query = "UPDATE links SET orders=orders+1 WHERE orders>$orders ORDER BY orders DESC";
mysql_query($query);
$query = "INSERT INTO `mydb`.`mytable` (`orders`) VALUES ($orders+1);";
mysql_query($query);
}
}
The default value takes care of id and timestamp, you don't enter these.