I am using the Perl DBI module with MySQL and trying to get the initial value before adding 1 to it when updating a row.
If the current value was 1000 I need to return the value of 1000 and then add 1 to the value.
I use this statement in perl to use one transaction...
update TABLE_NAME set ID = (\#cur_value := ID) + 1
I know I can do a select then an update as two statements or lock the tables manually but transactions happen so fast on our platform that it may cause inconsistencies and this is the fastest way to do it.
However I simply cannot find a way to return the original value before the increment using this statement.
It works fine in ASP as below:
qry = "update V15_TRACKING set TRACKING_ID = (#cur_value := TRACKING_ID) + 1 where TRACKING_TYPE='ABC'"
Set oRS = oConn.Execute(qry)
qry = "select #cur_value"
if not oRS.EOF then
while not oRS.EOF
CurrTrackingID = oRs.Fields("#cur_value")
oRS.movenext
wend
oRS.close
end if
Please can someone advise me what I need to do to return the original value in Perl as I have searched everywhere and tried all sorts of solutions.
A snippet to show what you're actually doing in perl, and your result would help diagnose what is going on in your script.
I tried this trivial example:
The DB:
CREATE DATABASE TEST;
CREATE TABLE foo (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
val int(11) NOT NULL
);
INSERT INTO foo (val) VALUES (1);
And the Perl
#!/bin/env perl
use strict;
use warnings;
use Data::Dumper;
use DBI;
my $dbh = DBI->connect('DBI:mysql:database=test', 'dbuser', 'dbpass');
my $select = $dbh->prepare('SELECT * FROM foo WHERE id=?');
my $select_old_val = $dbh->prepare('SELECT #old_val');
my $update = $dbh->prepare('UPDATE foo SET val=(#old_val := val) + 1 WHERE id=?');
$update->execute(1);
$select_old_val->execute();
$select->execute(1);
while (my $row = $select_old_val->fetchrow_hashref) {
print Dumper $row;
}
while (my $row = $select->fetchrow_hashref) {
print Dumper $row;
}
And after a few goes:
$ perl select_and_update.pl
$VAR1 = {
'#old_val' => '10'
};
$VAR1 = {
'id' => '1',
'val' => '11'
};
Related
I constantly need to "reset" the AUTO_INCREMENT value of my tables, after I delete a part of my rows. Let me explain with an actual example :
I have a table called CLIENT. Let us say before removing some rows, the auto_increment was set to 11. Then I delete the 4 lasts rows. The auto_increment is still set to 11. So when I will insert some clients again, it will make a hole of id.
I always need to "clean" the auto_increment, e.g. using this function below :
function cleanAutoIncrement($tableName, $columnAutoIncrement, $pdo)
{
$r = false;
try {
$p = $pdo->prepare("SELECT IFNULL(MAX($columnAutoIncrement) + 1, 1) AS 'max' FROM $tableName LIMIT 1;");
$p->execute();
$max = $p->fetch(PDO::FETCH_ASSOC)['max'];
$p = $pdo->prepare("ALTER TABLE $tableName AUTO_INCREMENT = $max;"):
$p->execute();
$r = true;
}
catch(Exception $e) {
$r = false;
}
return $r;
}
What the function do is to get the maximum id in the table, then increments it of 1, and return its value (if there was no rows in table, it return 1). Then I alter the table to reset a "clean" id in order not to let any hole of id.
QUESTION
Is there any MySQL command to perform this task without having to do this manually ?
To close this question, no shortcut exists in MySQL and it is not recommended to perform this task.
I am new in perl programming language. Can you please guide how to write csv upload into mysql database.
I have following table & csv file format
Create Table:
CREATE TABLE consumeruser (
ConsumerId int(10) NOT NULL AUTO_INCREMENT,
ConsumerName varchar(45) DEFAULT NULL,
ConsumerMobNo varchar(10) DEFAULT NULL,
PRIMARY KEY (ConsumerId)
) ENGINE=InnoDB AUTO_INCREMENT=4494 DEFAULT CHARSET=latin1
Csv file example:
4495,Sanchita Mehra,999999999
4496,Rupesh Shewalkar,88888888
4497,Aditya Mishra,111111111
Csv upload should be on basis of mobile number, suppose if table already contain mobile 111111111 Then that row should be skip. Means all mobile numbers should be check with existing data, if it is already in database that row should not be insert in database & rest of inserted into database.
You can check for the count of the row to see if the data is already present and then continue to next statement if its present. The implementation is for SQLite and you can change it to MySQL.
#!/usr/bin/perl
use Modern::Perl '2012';
use DBD::SQLite;
use warnings;
my $dbh = DBI->connect("dbi:SQLite:dbname=Consumer");
while(<DATA>){
chomp;
my ($id, $name, $MobNo) = split /,/;
my $query = "select count(*) from consumeruser where ConsumerMobNo = ?";
my $sth = $dbh->prepare($query);
$sth->execute($MobNo);
my $row = $sth->fetch();
next if(#$row > 0);
my $insertStatement = "insert into consumeruser values(?,'?',?)";
$sth = $dbh->prepare($insertStatement);
$sth->execute($id,$name,$MobNo);
}
__DATA__
4495,Sanchita Mehra,999999999
4496,Rupesh Shewalkar,88888888
4497,Aditya Mishra,111111111
4498,Aditya,111111111
Edit:
For fetching all the mobile numbers in the array. You can do like this.
my #MobileNumbers;
my $mobileNumberQuery = "select ConsumerMobNo from consumeruser";
my $sth = $dbh->prepare($mobileNumberQuery);
$sth->execute();
while(my $row = $sth->fetch()){
push #MobileNumbers, #$row;
}
Please refer to perldoc DBI for various ways of accessing the results.
What is the best way to check if a table exists in MySQL (preferably via PDO in PHP) without throwing an exception. I do not feel like parsing the results of "SHOW TABLES LIKE" et cetera. There must be some sort of boolean query?
Querying the information_schema database using prepared statement looks like the most reliable and secure solution.
$sql = "SELECT 1 FROM information_schema.tables
WHERE table_schema = database() AND table_name = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$tableName]);
$exists = (bool)$stmt->fetchColumn();
If you're using MySQL 5.0 and later, you could try:
SELECT COUNT(*)
FROM information_schema.tables
WHERE table_schema = '[database name]'
AND table_name = '[table name]';
Any results indicate the table exists.
From: http://www.electrictoolbox.com/check-if-mysql-table-exists/
Using mysqli I've created following function. Assuming you have an mysqli instance called $con.
function table_exist($con, $table){
$table = $con->real_escape_string($table);
$sql = "show tables like '".$table."'";
$res = $con->query($sql);
return ($res->num_rows > 0);
}
Hope it helps.
Warning: as sugested by #jcaron this function could be vulnerable to sqlinjection attacs, so make sure your $table var is clean or even better use parameterised queries.
This is posted simply if anyone comes looking for this question. Even though its been answered a bit. Some of the replies make it more complex than it needed to be.
For mysql* I used :
if (mysqli_num_rows(
mysqli_query(
$con,"SHOW TABLES LIKE '" . $table . "'")
) > 0
or die ("No table set")
){
In PDO I used:
if ($con->query(
"SHOW TABLES LIKE '" . $table . "'"
)->rowCount() > 0
or die("No table set")
){
With this I just push the else condition into or. And for my needs I only simply need die. Though you can set or to other things. Some might prefer the if/ else if/else. Which is then to remove or and then supply if/else if/else.
Here is the my solution that I prefer when using stored procedures. Custom mysql function for check the table exists in current database.
delimiter $$
CREATE FUNCTION TABLE_EXISTS(_table_name VARCHAR(45))
RETURNS BOOLEAN
DETERMINISTIC READS SQL DATA
BEGIN
DECLARE _exists TINYINT(1) DEFAULT 0;
SELECT COUNT(*) INTO _exists
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name = _table_name;
RETURN _exists;
END$$
SELECT TABLE_EXISTS('you_table_name') as _exists
As a "Show tables" might be slow on larger databases, I recommend using "DESCRIBE " and check if you get true/false as a result
$tableExists = mysqli_query("DESCRIBE `myTable`");
$q = "SHOW TABLES";
$res = mysql_query($q, $con);
if ($res)
while ( $row = mysql_fetch_array($res, MYSQL_ASSOC) )
{
foreach( $row as $key => $value )
{
if ( $value = BTABLE ) // BTABLE IS A DEFINED NAME OF TABLE
echo "exist";
else
echo "not exist";
}
}
Zend framework
public function verifyTablesExists($tablesName)
{
$db = $this->getDefaultAdapter();
$config_db = $db->getConfig();
$sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '{$config_db['dbname']}' AND table_name = '{$tablesName}'";
$result = $db->fetchRow($sql);
return $result;
}
If the reason for wanting to do this is is conditional table creation, then 'CREATE TABLE IF NOT EXISTS' seems ideal for the job. Until I discovered this, I used the 'DESCRIBE' method above. More info here: MySQL "CREATE TABLE IF NOT EXISTS" -> Error 1050
Why you make it so hard to understand?
function table_exist($table){
$pTableExist = mysql_query("show tables like '".$table."'");
if ($rTableExist = mysql_fetch_array($pTableExist)) {
return "Yes";
}else{
return "No";
}
}
I'm having a problem with running this function. When it runs, it does exactly what I want, except that within my like_requests table the request_id is not the mysql query result linked to the variable $select but Resource Id #22. I thought that resource id's appear when you are trying to echo out a result, but I'm not using echo. What's wrong with the code?
function update_likes($band_requested, $new_likes, $session_user_id) {
$select = mysql_query("SELECT `primary_id` FROM `requests` WHERE
`user_requester_id` = '$session_user_id' AND `person_requested` =
'$band_requested'");
$sql_2 = "INSERT INTO `like_requests` (user_id, request_id) VALUES
('$session_user_id', '$select')";
mysql_query($sql_2);
}
$band_requested = 'rally done';
$new_likes = 239;
$the_session_user_id = 3;
update_likes($band_requested, $new_likes, $the_session_user_id);
UPDATE WITH CORRECTED ANSWER
Here is the code corrected with help from David.
function update_likes($band_requested, $new_likes, $session_user_id)
{
$select = mysql_query("SELECT `primary_id` FROM `requests` WHERE `user_requester_id` =
'$session_user_id' AND `person_requested` = '$band_requested'");
$row = mysql_fetch_row($select);
$request_id = $row[0];
$sql_2 = "INSERT INTO `like_requests` (user_id, request_id) VALUES ('$session_user_id',
'$request_id')";
mysql_query($sql_2);
}
mysql_query returns a resource (http://php.net/manual/en/function.mysql-query.php) not just a scalar value. You'd need to use a function like mysql_fetch_row() to get the, presumably, one row you want, assign that row to a variable $row, then retrieve the primary_id with array syntax like $row['primary_id']. By the way, apparently mysql_query is being eased out and we should use the MySQLi API with the mysqli_query() method.
I am having an issue with inserting an array of information into a mysql database. Basically I built a sortable gallery similar to Facebook's photo albums that can be arranged by moving the div to a new spot with jquery's sortable function.
I am using Ajax to call a php file which will inser the new order of the div's into the DB. The information is being passed correctly, it is just not being inserted correctly.
The error I am receiving is:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Array' at line 1
The Php code is:
foreach ($_GET['listItem'] as $position => $item) {
if ($item >= 1) {
$sql[] = "UPDATE table SET order = '{$position}' WHERE id = '{$item}'";
mysql_query($sql) or die(mysql_error());
}
}
If I remove the mysql_query function and just do a print_r, I get:
Array
(
[0] => UPDATE table SET order = '0' WHERE id = '2'
[1] => UPDATE table SET order = '1' WHERE id = '4'
[2] => UPDATE table SET order = '2' WHERE id = '3'
[3] => UPDATE table SET order = '3' WHERE id = '1'
[4] => UPDATE table SET order = '4' WHERE id = '5'
[5] => UPDATE table SET order = '5' WHERE id = '6'
)
This is the first time I have tried to do something like this. Any help would be great.
Thank you in advance for the help!
In mysql_query($sql) $sql is an array, therefore it's value is simply Array. When you assign $sql[] = "UPDATE table SET order = '{$position}' WHERE id = '{$item}'"; simply make this line $sql = "UPDATE table SET order = '{$position}' WHERE id = '{$item}'";. That should solve your problem.
EDIT:
You can leave the [] and simply remove the mysql_query from where it is. After your foreach list item, add this:
foreach($sql as $query) {
mysql_query($query);
}
Sounds like there is some confusion about what the [] operator does. You use [] when you want to append an element to the end of an existing array.
For example:
$sql = array();
$sql[] = 'UPDATE table SET order = "0" WHERE id = "2"';
mysql_query($sql); // this will produce the error you are seeing
Versus:
$sql = 'UPDATE table SET order = "0" WHERE id = "2"';
mysql_query($sql); // this will work
You should rewrite your code as such:
foreach ($_GET['listItem'] as $position => $item) {
if ($item >= 1) {
$sql = "UPDATE table SET order = '{$position}' WHERE id = '{$item}'";
mysql_query($sql) or die(mysql_error());
}
}
That will do what you are intending. However, this is still not a good idea, since you are passing untrusted $_GET data directly to the database. I could, for example, call your script with a string like:
http://yoursite.com/yourscript.php?listItem=1'%3B%20DROP%20TABLE%20yourtable%3B
Since the value of listItem is going directly to the database -- and the $item >= 1 check is insufficient, since PHP will evaluate a string as an integer if it begins with numeric data -- all I have to do is add a single quote to terminate the previous query, and I am then free to inject whatever SQL command I'd like; this is a basic SQL injection attack. Whenever you write database-touching code, you should cleanse any input that might be going to the database. A final version of your code might look like:
foreach ($_GET['listItem'] as $position => $item) {
if ($item >= 1) { // this check may or may not be needed depending on its purpose
$sql = 'UPDATE table SET order = "' . mysql_real_escape_string($position) . '" WHERE id = "' . mysql_real_escape_string($item) . '"';
mysql_query($sql) or die(mysql_error());
}
}
There are other ways to cleanse input data as well, that is just one of them. Hope that helps.