Geometry field issue with MariaDB and PHP prepared statement - php

From a PHP script, using mysqli prepared statement to INSERT a row, I'm getting an error returned from MariaDB on a field of type POINT. Code looks a something like this:
$sql = 'INSERT INTO reports (location) VALUES (?)';
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $variable);
$variable = 'POINT(10,10)';
$stmt->execute();
location is intended to store GPS co-ordinates and is defined as point data type in it's column definition. The error which is returned in the resulting stmt object has errno = 1416 error = Cannot get geometry object from data you send to the GEOMETRY field.
Other columns of varchar type work without issue, so I'm guessing it is somewhere in the underlying table definition being POINT data type and the presentation of the intended data POINT (10, 10) as a string type in the prepared statement. I had initially thought about just storing lat, lon as individual DECIMAL columns but the POINT data type may serve future purposes much better.
In the MariaDB monitor, the statement:
INSERT INTO reports (location) VALUES (POINT(10,10));
will work fine and insert the row into the database table.
Also, if I were to use mysqli_query (which I don't intend using) as follows;
$variable = 'POINT(20, 20)';
$sql = "INSERT INTO reports (location) VALUES ($variable)";
mysqli_query($mysqli, $sql)
it works as intended.
So, my query is how in PHP, to replicate the working MariaDB monitor statement or mysqli_query() example via a mysqli prepared statement.

POINT isn't a string, it's an SQL function. MariaDB isn't smart enough to convert strings to SQL, so you cannot bind it as a string. You can bind the parameters of POINT but not the SQL itself.
The following should work fine:
$sql = 'INSERT INTO reports (location) VALUES (POINT(?,?))';
$stmt = $mysqli->prepare($sql);
$stmt->execute([10,10]);

Related

How do I view the Bind variables from a PHP Prepared Statement on SQL Server 2012?

I have read the SO question about Oracle's Bind equivalent. This is four years later, however. I have looked at sp_executesql from
https://msdn.microsoft.com/en-us/library/ms188001.aspx?f=255&MSPPError=-2147217396
I am not using T-SQL or any sort of Stored Procedure, only a PHP Prepared Statement (using PDO).
How can I view my bound value in SQL Server 2012? If there is a way for me to use sp_executesql, I do not know how to use it.
EDIT: When I say view, I mean a table in SQL Server.
EDIT: I am trying to find out the value that was received by SQL Server. I want to query a view, table, run a stored procedure, something so I can see what SQL Server actually received.
Here is a similar question:
What is the SQL Server equivalent of Oracle bind variables in dynamic SQL?
This is what it is in Oracle 11g:
http://docs.oracle.com/cd/B19306_01/server.102/b14237/dynviews_2114.htm#REFRN30310
"V$SQL_BIND_CAPTURE displays information on bind variables used by SQL cursors. Each row in the view contains information for one bind variable defined in a cursor. This includes:"
EDIT:
Example,
$sql = "SELECT * FROM employees where employeeid = :mykey";
$prepared_statement = $this->_adapter->prepare($sql);
$prepared_statement->bindValue(':mykey', $_employee_search, PDO::PARAM_INT);
$prepared_statement->execute();
I wan to know :mkey after it has been sent to SQL Server.

Using the data of the index column I just added

I was just reading about PDO::lastInsertId from the PHP documentation, but after some tests I reallized I absolutelly suck at PHP xD and I should investigate more about classes and static methods and more to even understand where to put that code.
Anyway, I'm not actually trying to know the last Inserted Id, I want to get the Index value of the last inserted row of MySQL table. My Index column is called "id" and is set to auto increment everytime I add a new row, yet, when I delete a row the number doesn't update, so the value in the row called "id" may not allways be the same as the row number.
Here is the code that inserts a new row.
<?php
require('conexion.php');
$name=$_POST['name'];
$email=$_POST['email'];
$pass=$_POST['pass'];
$localidad=$_POST['localidad'];
$saldo=$_POST['saldo'];
$slastupdate=$_POST['slastupdate'];
$query="INSERT INTO usuarios (name, email, pass, localidad, saldo, slastupdate) VALUES ('$name','$email','$pass','$localidad','$saldo','$slastupdate')";
$resultado=$mysqli->query($query);
?>
Update: For now on, I'm using another query to get the last inserted's row Id... In my case using PDO is not necessary since I'm developing a private app, and there's no risk of mysql injections
require_once "../php/new_mysql.php";
$query="INSERT INTO clientes (gira, localidad, nombre, email, proxivisi, saldo) VALUES ('$gira', '$localidad', '$nombre', '$email', '$proxivisi', '$saldo')";
$agregar=$mysql->query($query) or die(mysql_error());
$querygetid=$mysql->query("SELECT id, proxivisi FROM clientes WHERE nombre='$nombre' AND email='$email'");
$getid=$querygetid->fetch_assoc();
$id=$getid['id'];
#FranCano use #user to notify us of your reply.
Your first problem is you seem to be using mysqli, not PDO in the above code. mysqli and PDO are different APIs to run MySQL queries and don't share functions. PDO::lastInsertId will give you the auto increment value of the last inserted row.
Start with PDO::__construct() to see how to start a PDO instance and connect to a database. Check PDO::query() and the examples listed to see how PDO works. However, PDO::query() is basic and does not protect you from SQL injections. For your above query you should be used prepared statements since you use user input (POST). Prepared statements are started with PDO::prepare(). MySQLi has prepared statements too but they are slightly different.
PDO is object oriented, you can't just call PDO::query() and PDO::lastInsertId(). You create a PDO instance to connect to the database, then you create a PDOStatement object by using prepare(), then you execute (PDOStatement::execute) that PDOStatement object to run the query. Then you can resort to the lastInsertId() on the original PDO object.
If you don't know OOP or object oriented programming then this will all sound pretty confusing so that is where you need to start your reading.
A quick example is:
$pdo = new PDO(..mysql connection information..);
// Create a PDOStatement object
$stmt = $pdo->prepare("INSERT into test ('field1', 'field2') VALUES (?, ?)");
// Execute the prepared statement safely inserting the post variables into the ?'s. This protects against SQL injection attacks.
if ($stmt->execute(array($_POST['value1'], $_POST['value2']))) {
$id = $pdo->lastInsertId();
}

how to insert data from primary key column to foregin key

i am inserting data from a form i want when i will insert data so the first column primary id which is using in second column as a foreign key should be increased
i have tried this code but not working
first table code
$this->db->query("insert into af_ads (ad_title,ad_pic,ad_description)
values ('$title','$filepath','$description')");
second table code
$this->db->query("insert into af_category (cat_type,ad_id_fk)
values ('$category','ad_id')");
NOTE: i want to insert ad_id into ad_id_fk
Try this:
// Your first query
$this->db->query("insert into af_ads(ad_id, ad_title, ad_pic, ad_description)
values ('', '$title', '$filepath', '$description')");
$ad_id = $this->db->insert_id(); // This returns the id that is automatically assigned to that record
// Use the id as foreign key in your second insert query
$this->db->query("insert into af_category (cat_type,ad_id_fk)
values ('$category', $ad_id)");
MySQL provides the LAST_INSERT_ID function as way to retrieve the value generated for an AUTO_INCREMENT column from the immediately preceding INSERT statement.
A lot of client libraries make this conveniently avaiable (e.g. PDO lastInsertId function.)
(I'm not familiar with CodeIgniter or ActiveRecord, so I can't speak to how that's made available.
Your code looks like it's using the PDO interface... but I'm not sure about that.
# either we need to check return from functions for errors
# or we can have PDO do the checks and throw an exception
$this->db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
# attempt insert which will generate AUTO_INCREMENT value
$this->db->query("INSERT (ad_id, ... ) VALUES (NULL, ...)");
# if previous insert successfully inserted a row (or rows)
$ad_id = $this->db->lastInsertId();
You really need to check whether the previous insert was successful or not. If you aren't going to code that check yourself, then PDO does provide a mechanism that performs this checking automatically, and will throw an exception if a MySQL error occurs.
I've avoided copying your original code, which looks like it's vulnerable to SQL Injection. If you're using PDO, you can make effective use of prepared statements with bind placeholders, rather than including values in the SQL text.

mysqli_stmt_bind_param variable type

I'm converting from mysql_ to mysqli_ and still new to mysqli_. Here is my code:
$stmt = mysqli_prepare($con, "INSERT INTO test VALUES (?, ?)");
mysqli_stmt_bind_param($stmt, 'ss', $a, $b);
$a=1;
$b=1.5;
mysqli_stmt_execute($stmt);
My question is:
$a has Integer value
$b float
but the corresponding variable type in mysqli_stmt_bind_param ss (string,string).
the result is data succesfuly inserted to table, is work as intended or i'm doing wrong?
Actually bind functions (mysqli_stmt_bind_param or PDOStatement::bindParam) are not validation functions. You show how to interpret your value only and what type of value you want to get from result.
Answer is: it is work as intended.
Are the fields in the table that this statement targets set up as integer/floats? Or are they set up as strings in the database (some people do this, for whatever reason). Also, as for prepared statements being slower, I believe that is only the case when running a run once unique query. If you are making several queries in a loop, prepared statements are, I believe, significantly faster (provided the statement was constructed outside of the loop).
The source variable can be of any type really, but it will attempt to convert to string when preparing the query because thats the type you said the query takes.
What really matters are the types of the fields in the table. I'm not sure how PHP handles this but if the query takes an integer (i) and you try to prepare it as a string (s) it may cause an error. In any case you should specify the correct type to avoid problems.

Why doesn't PDO's Oracle driver implement lastInsertId()?

I get this error in PDO:
error: Message: PDO::lastInsertId() [pdo.lastinsertid]:
SQLSTATE[IM001]: Driver does not support this function: driver does
not support lastInsertId()
when trying to get last inserted id from an oracle database. I added the sequence string to the last insert id function but still not working. Google doesn't say much regarding this error on Oracle with PDO.
Oracle doesn't have autoincrement columns, so lastInsertId isn't supported in the same way as for MySQL. You have to implement the equivalent "by hand" using Oracle sequences.
Create an oracle sequence for every table that requires it, and use NEXTVAL to retrieve it whenever you need to do an insert, then use that value when inserting in the table.
$sh = $conn->prepare('SELECT uid_seq.NEXTVAL AS nextInsertID FROM DUAL');
$sh->execute();
$nextInsertId = $sh->fetchColumn(0);
$sh = $conn->prepare("INSERT INTO table (id, data) VALUES(?, 255)");
$sh->execute(array($nextInsertId));
In Oracle, you should have created an oracle sequence for tables which requires an auto increment column.
If you want to insert, then you can do it in the same time rather than query nextIncrementId and insert as below:
$sh = $conn->prepare("INSERT INTO table (id, data) VALUES(SEQUENCE_NAME.NEXTVAL, ?)");
$sh->execute(array($valueToBeInsertedInDataColumn));
If you just want to know the last insert id, then don't use nextval because whenever you call it, it increment the value to the next one. You should use CURRVAL for that purpose. Below is an example:
$sh = $conn->prepare("SELECT SEQUENCE_NAME.CURRVAL AS lastInsertId FROM DUAL");
$lastInserId = $sh->execute();
Debug: print_r($lastInserId);

Categories