My query generates an ORA-00933 error, why is that? - php

I'm using php to generate an oracle query like this:
...
$sql = sprintf("INSERT INTO $table_name %s %s ON DUPLICATE KEY UPDATE ",
$this->prepare_insert_sql("", $fields, false),
$this->prepare_insert_sql(" VALUES ", $values, true));
for ($index = 0; $index < count($fields); $index++) {
if ($index > 0) {
$sql .= ", ";
}
$sql .= $fields[$index] . "='" . $values[$index] . "'";
}
...
And the result query is:
INSERT INTO TBL_CONFIG(KEY,VALUE)
VALUES ('1_default_meter_type_for_device_type_1','822')
ON DUPLICATE KEY
UPDATE KEY='1_default_meter_type_for_device_type_1', VALUE='822'
It gives an ORA-00933 error.
I really can't seem to find the error. Any tip is appreciated.

Using merge instead of insert into worked.
MERGE INTO TBL_CONFIG USING DUAL ON (KEY ='1_default_meter_type_for_device_type_1')
WHEN MATCHED THEN UPDATE SET VALUE = '822'
WHEN NOT MATCHED THEN INSERT (KEY, VALUE) VALUES ('1_default_meter_type_for_device_type_1', '822')

Per your posted code KEY is a reserve word and so you need to escape it using "" double quote like below
INSERT INTO TBL_CONFIG("KEY",VALUE)
VALUES ('1_default_meter_type_for_device_type_1','822')
ON DUPLICATE KEY
UPDATE "KEY"='1_default_meter_type_for_device_type_1', VALUE='822'
EDIT:
Totally confused. Oracle doesn't have ON Dulicate Key Update. You have to use MERGE statement as commented by Fred-ii.

Try this:
$sql = sprintf(
"INSERT INTO $table_name %s %s ON DUPLICATE KEY UPDATE ",
$this->prepare_insert_sql("", $fields, false),
$this->prepare_insert_sql(" VALUES ", $values, true)
);
for($index = 0; $index < count($fields); $index++) {
if($index > 0) {
$sql .= ", ";
}
// added " before and after field name
$sql .= '"' . $fields[$index] . '"=\'' . $values[$index] . "'";
}

Related

What is the purpose of strlen($query)-2;

I got this code from google and it fulfills my requirement, but I don't understand the meaning of this line:
substr($query,0,strlen($query)-2)
Could somebody explain it to me?
<?php
function insert($tablename, $parameter_order, $values)
{
$query = "insert into $tablename (";
foreach($parameter_order as $po)
{
$query .= $po.', ';
}
$query = substr($query,0,strlen($query)-2).') values (';
foreach($values as $v)
{
$query .= "'$v', ";
}
$query = substr($query,0,strlen($query)-2).');';
return $this->makeQuery($query);
}
?>
This is what those functions do exactly:
substr() is used to generate a sub-string of specified length from another string.
strlen() will return the length of the provided string.
Code substr($query,0,strlen($query)-2) removes comma and space from foreach Loop.
The line removes the last comma and space from $query. These characters have been added in the foreach loop to glue together the elements of $parameter_order.
Note that this standard task is usually done better with the implode() function:
$query = "insert into $tablename (" . implode (', ', $parameter_order) . ' ) values (';

iteration problems with foreach loop

I'm trying to make a function that creates a sql statement to insert data into a database and this is a snippet. It works fine except for the last foreach loop. For some reason it won't iterate to the last element in the array it'll stay stuck on the second last one. The issue is that the first foreach loop is the same code and it works fine, but the second is giving me trouble.
*note:The if statements in the foreach loops are supposed to catch the last element in the array and make sure that a ',' isn't inserted. And this is where the problem is. If I take the if statement out of the second loop the loop will iterate to the last element but without the if block it places a comma at the end and creates a SQL syntax error.
output of the first loop
INSERT INTO gardyloo.users (joe,bob,joe#hotmail.com,8de,154927,2014-12-18,2014-12-18 7:02:11)
output of second loop without if
VALUES (:firstName,:lastName,:emailAddress,:password,:userid,:date_joined,:timestamp,)
output of second loop with if
VALUES (:firstName,:lastName,:emailAddress,:password,:userid,:date_joined)
foreach( $values as $a => $b ){
if(next($values) == null){
$sql .= $b."";
break;
}
$sql .= $b.",";
}
$sql .= ") ";
$sql .= "VALUES (";
foreach( $values as $a => $b ){
if(next($values) == null){
$sql .= ":".$a;
break;
}
$sql .= ":".$a.",";
}
$sql .= ")";
*Edit, this code seems to work fine:
$sql .= implode(', ', array_keys($values));
$sql .= ") ";
$sql .= "VALUES (:";
$sql .= implode(", :", array_keys($values));
$sql .= ")";
Instead of break you need to use continue; Break interrupts the loop, while continue only move to next iteration.
Try this:
foreach( $values as $a => $b ){
if($b == null){
continue;
}
$sql .= ":".$a.",";
}
Do something like this:
//Your data
$values = array(
'firstName' => 'Joe',
'lastName' => 'bob',
'emailAddress' => 'joe#hotmail.com',
'password' => '8de',
'userid' => 154927,
'date_joined' => '2014-12-18',
'timestamp' => '2014-12-18 7:02:11'
);
//Begins the sentence
$sql = 'INSERT INTO gardyloo.users(';
/**
* Begins example code.
* - array_keys shows the key as a value
* example: $values[0] = firstName
*/
foreach(array_keys($values) as $k => $v)
{
//when the array arrives at the end, doesn't show ','
if($k != count($values)-1)
$sql .= $v.",";
else
$sql .= $v;
}
$sql .= ") ";
$sql .= "VALUES (";
$k = 0;//the new count initialized
foreach($values as $v)
{
//when the array arrives at the end, doesn't show ','
if($k != count($values)-1)
$sql .= $v.",";
else
$sql .= $v;
//increments the counter
$k++;
}
$sql .= ");";
Notes:
Separate the code in functions since both foreachs are very similar.
You can play with the foreach values to return the value that you want.
Ask me if you have more questions about it.
I'll do it otherwise. Instead of concat a string $sql create 2 variables, $columns and $values, both are arrays. And you don't need a loop to do this.
So here is how i would do it :
$columns = array_keys($values);
$sql = "INSERT INTO table (". implode(" ,", $columns) . ") VALUES (". implode(" ,", $values);
Here you don't need to test if it's the last element of the array to make a break;
Hope it helps ;)

More elegant way in PHP to generate a query from array elements

When I need to loop over something while generating a query from each element, I would use something like
$queryStr = "INSERT INTO tableName (x,y) VALUES ";
for ($i = 0 ; $i < $len ; $i++)
{
$queryStr .= "( ".$thing[$i]['x'].", ".$thing[$i]['b']."), ";
}
//extra code to remove the last comma from string
Would there be an alternative?
I don't mind performance too much (knowing the length of the array is not too big), just something that looks nicer.
Using a prepared statement:
$sql = 'INSERT INTO tableName (x, y) VALUES (:x, :y)';
$sth = $dbh->prepare($sql);
for ($i = 0 ; $i < $len ; $i++)
{
$sth->execute(array(
':x' => $thing[$i]['x'],
':y' => $thing[$i]['b']));
}
More examples: http://www.php.net/manual/en/pdo.prepare.php
A slight improvement to get rid of last part (removing latest comma). You can first create an array of values, then use implode function like:
$queryStr = "INSERT INTO tableName (x,y) VALUES ";
for ($i = 0 ; $i < $len ; $i++)
{
$values[] = "( ".$thing[$i]['x'].", ".$thing[$i]['b'].")";
}
$queryStr .= implode(',', $values);
I like using array_walk and implode for things like this:
$values = array(
array(1, 2, 3),
array(4, 5, 6),
. . .
);
// an array to hold the values to insert
$query = array();
// walk the values and build the query array
array_walk($values, function($v) use(&$query) {
$query[] = "(" . implode(", ", $v) . ")";
});
// dump the output
echo implode(", ", $query);
The result looks like this:
(1, 2, 3), (4, 5, 6), ...
Maybe not much cleaner, but at least it gets rid of the for loop :-)
You could use implode() with array_map():
implode(', ', array_map(function($v) { return '(' . $v['x'] . ', ' . $v['b'] . ')'; }, $things));
Demo
$strCols = '`'.implode('`, `',array_keys($arrValues)).'`'; //Sets the array keys passed in $arrValues up as column names
if ($bolEscape){ //Checks if $bolEscape is true
$arrValues = $this->escape($arrValues); //Calls the escape function
$strValues = '"'.implode('","',array_values($arrValues)).'"'; //Sets the array values passed in $arrValues up as data for the columns
}else{
$strValues = '"'.implode('","',array_values($arrValues)).'"'; //Sets the array values passed in $arrValues up as data for the columns WITHOUT escaping
}
//Creates the SQL statement for the query
$strSQL = 'INSERT INTO `' . $strTable . '` (' . $strCols . ') VALUES (' . $strValues . ')';
Thats part of the database class I have written... I pass in the arrValues ('ColumnName'=>'Value')

Insert multiple rows using single query

I want to insert multipl rows in single query.
$firstname = array('Arfan','Awais','Ahmad'.....);
$lastname = array('Haider','k','Raza'..........);
Insert Data:
INSERT INTO `table_nmae`(firstname,lastname)
VALUES
('Arfan','Haider'),('Awais','k'),('Ahmad','Raza');
I can do it very easily if these are only three record.
If I did not know how many records are present then I can not able to use the above.
Then what I did do?
UPDATE:
If I can not know the numbers of record in array.I can simply use foreach loop to do this
But this decrease the performance.
foreach($firstname as $f){
foreach($lastname as $l){
INSERT INTO `table_name`(firstname,lastname)
VALUES('$f','$l');
}
}
Now this time I am using multi query.I think single query is good to performance.
FOR ONE COLUMN:
If I had only one column it is very easy to use single query for this.
INSERT INTO `table_name`(firstname) VALUES
.implode(',', $firstname);
But here is multi column how can I do that for those.
Thanks.....
Use for loop if $firstname and $lastname array are of same length
$str = "INSERT INTO `table_nmae`(firstname,lastname) VALUES"; // create string of query
for($i = 0 ;$i< count($firstname); $i++) {
$str .= "('" . $firstname[$i] . "','" . $lastname[$i] . "'),"; //append the values
}
$str = trim($str, ","); // remove last ,
Try
$size_of_array = count( $firstname );
$query = "INSERT INTO `table_nmae`(firstname,lastname) VALUES ";
for($i = 0; $i < $size_of_array; $i++ )
{
if( $i !== ($size_of_array-1))
$query .= "('{$firstname[$i]}', '{$lastname[$i]}'),";
else
$query .= "('{$firstname[$i]}', '{$lastname[$i]}')";
}
echo $query;
?>
Suppose you have array of values e.g. $values_arr.
$count = count( $values_arr );
$query = "INSERT INTO `table_nmae`(firstname,lastname) VALUES ";
for($i = 0; $i < $count; $i++ )
{
if( $i == 0)
$query .= "('{$values_arr[$i]['firstname']}', '{$values_arr[$i]['lastname']}')";
else
$query .= ",('{$values_arr[$i]['firstname']}', '{$values_arr[$i]['lastname']}')";
}
echo $query;

Foreach loop with multiple arrays [duplicate]

This question already has answers here:
Two arrays in foreach loop
(24 answers)
Closed last month.
This is what I want:
foreach($_POST['something'] as $something){
foreach($_POST['example'] as $example){
$query = mysql_query("INSERT INTO table (row, row2) VALUES ('{$something}','{$example}')");
}
}
$_POST['something'] and $_POST['example'] are arrays from an input with
name="something[]" and name="example[]".
The problem:
In this way I will send the data twice to database. So I need a solution where I can loop trough 2 arrays without seding the data twice.
EDIT
The two array will always have the same size
In the mysql_query I will have other elements not just row, row2, and those will be static without any array.
Do you mean something like:
foreach($_POST['something'] as $key => $something) {
$example = $_POST['example'][$key];
$query = mysql_query("INSERT INTO table (row, row2) VALUES ('{$something}','{$example}')");
}
SOLUTION FOR MULTIPLE Arrays
TRY -
1)
<?php
$ZZ = array('a', 'b', 'c', 'd');
$KK = array('1', '2', '3', '4');
foreach($ZZ as $index => $value) {
echo $ZZ[$index].$KK[$index];
echo "<br/>";
}
?>
or 2)
<?php
$ZZ = array('a', 'b', 'c', 'd');
$KK = array('1', '2', '3', '4');
for ($index = 0 ; $index < count($ZZ); $index ++) {
echo $ZZ[$index] . $KK[$index];
echo "<br/>";
}
?>
Your solution does not seem to send the data twice. Unless if records with the same values appear as a result of issuing your queries. This might mean that you should process your data before constructing your queries.
One solution could be:
$sql = array();
foreach($_POST['something'] as $something){
foreach($_POST['example'] as $example){
$sql[] = "INSERT INTO table (row, row2) VALUES ('{$something}','{$example}')";
}
}
foreach($sql as $query){
mysql_query($query);
}
I think the best way would be as a single loop to build a query. This should work even if your arrays are not the same length:
$size1 = count($_POST['something']);
$size2 = count($_POST['example']);
if( $size1 >= $size2 ) {
$size = $size1;
} else {
$size = $size2;
}
$sql = "INSERT INTO table (row, row2) VALUES";
$values = array();
for( $i=0; $i<$size; $i++ ) {
$values[] = "('" . mysql_real_escape_string($_POST['something'][$i]) . "','" . mysql_real_escape_string($_POST['example'][$i]) . "')";
}
$sql .= implode(",", $values);
mysql_query($sql);
Also more secure because it escapes your input. This would also be even easier using placeholders with PDO.
$cnt = count($_POST['something']);
$cnt2 = count($_POST['example']);
if ($cnt > 0 && $cnt == $cnt2) {
$insertArr = array();
for ($i=0; $i<$cnt; $i++) {
$insertArr[] = "('" . mysql_real_escape_string($_POST['something'][$i]) . "', '" . mysql_real_escape_string($_POST['example'][$i]) . "')";
}
$query = "INSERT INTO table (column, column2) VALUES " . implode(", ", $insertArr);
mysql_query($query) or trigger_error("Insert failed: " . mysql_error());
}
Here is another method. This one uses extended inserts, so should be more efficient and quicker, and utilizes mysql_real_escape_string for security reasons. The count check is to just make sure that both fields have the same count, if not then I take this is a mishap. If they are allowed to have a different number of fields, you can simply use the isset() function to check to make sure they contain a value.
EDIT
This is assuming of course, that you do not want 'something' to iterate over all the 'example' values and be assigned to each one. If you want that well it is a bit of a change up.
Added an insert array test, if there are no elements no need to update. Thanks Gumbo for that.
Although you already selected an answer, don't forget this piece of script may fail if the POST values are not arrays. You can overcome this with a small piece of code:
$something = is_array($_POST['something']) ? $_POST['something'] : array();
$example = is_array($_POST['example']) ? $_POST['example'] : array();
/* Get all the keys from both arrays
* If they don't share the keys, none will be lost
*/
$keys = array_merge(array_keys($something),array_keys($example));
$keys = array_unique();
if (count($keys)) {
$sql = 'INSERT INTO table (row, row2) VALUES ';
$values = array();
foreach ($keys as $key) {
// Single quotes for PHP, we are not expanding variables
// If the element cannot be converted into a string, don't show the error on screen
$values[] = '("' . #mysql_real_escape_string($something[$key]) . '","' . #mysql_real_escape_string($example[$key]) . '")';
}
$sql .= implode(',', $values);
mysql_query($sql);
}
Foreach loop with multiple arrays:
foreach($_POST['quantity'] as $key=>$quantity)
{
$product_no=$_POST['product_id'][$key];
echo $product_no;
echo $quantity;
}
Yours example dont work in me.
I made like this :
if($_POST[add_all])
{
$n=0;
foreach($_POST['pieces'] as $checked)
{
if ($checked!=0)
{
$box=$_POST['box'];
echo $box[$n]." ".$checked . ' <br>';
$n++;
}
}
<input type="submit" id="coin" name="add_all" value="..Test.."><BR>
<select name="pieces[]">
<?php for ($x=0;$x<=20;$x++){ echo "<option>$x</option>";} ?>
<input type="checkbox" name="box[]" value="<?php echo"$row_produkt";?>">

Categories