hi im rather new to SQL and im currently trying to save some data into a Sql database using a website. But everytime i run it i get some Syntax error and now after many hours of looking i was hoping somebody in here knew an answer, or could lead me in the right direction :)
this is the error i get when i hit my submit button :
0You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '[Campus one],[101],[2016-12-08],[test])' at line 1
this is the insert part of the script, connection part seems to be running fine
$sql = "INSERT INTO `formel`(`Område`, `Værelse`, `Dato`, `TV Fjernsyn Forlænger`) VALUES ([$area],[$filnavn],[$dato],[$Fjernsyn]) ";
SQL information:
Your values need to be changed from:
[$area],[$filnavn],[$dato],[$Fjernsyn]
to:
'{$area}','{$filnavn}','{$dato}','{$Fjernsyn}'
You should really be binding your params though. I assume you're using mysql_ which you shouldn't be using anymore therefore I also suggest you look into mysqli_ or PDO.
Edit:
You should move over to PDO in fairness, I did and I love it!
I work with classes a lot as it's a neater way to work so I'll give you my input:
Make yourself a dbConfig.php file:
class Database
{
private $host = "localhost";
private $db_name = "dbName";
private $username = "username";
private $password = "password";
public $conn;
public function dbConnection()
{
$this->conn = null;
try
{
$this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $exception)
{
echo "Connection error: " . $exception->getMessage();
}
return $this->conn;
}
}
So because i am half lazy and why type code over and over?
Create yourself a dbCommon.php file.
class DBCommon
{
private $conn;
/** #var Common */
public $common;
public function __construct()
{
$database = new Database();
$db = $database->dbConnection();
$this->conn = $db;
}
public function runQuery($sql)
{
$stmt = $this->conn->prepare($sql);
return $stmt;
}
}
Then you need a class file for your PDO to go into such as:
class.update.php:
require_once('dbCommon.php');
class Update extends DBCommon
{
function __construct()
{
parent::__construct();
}
public function updateCode($area, $filnavn, $dato, $Fjernsyn)
{
$stmt = $this->runQuery("INSERT INTO `formel` (`Område`, `Værelse`, `Dato`, `TV Fjernsyn Forlænger`) VALUES (:area, :filnavn, :dato, :Fjernsyn)");
$stmt->bindParam(array(':area' => $area, ':filnavn' => $filnavn, ':dato' => $dato, ':Fjernsyn' => $Fjernsyn));
$stmt->execute();
echo "Your insert command has been completed!";
}
}
Then within your file.php where you would be calling the class you need to do:
require_once ('class.update.php');
$update = new Update();
if (isset($_POST['send']))
{
$update->updateCode($_POST['area'], $_POST['filnavn'], $_POST['dato'], $_POST['Fjernsyn']);
}
Note: Because you didn't post your $_POST['name']'s in I have given you a base example.
Binding your params is best practice as this prevents SQL Injection.
With binding params you dont have to run $stmt->bindParam(); You can simply run $stmt->execute(array(':paramshere' => $paramVar));
It totally depends on your preference but I always prefer binding before executing (personal preference). I hope this gives you some input and insight on how to move into PDO instead but it really is the way forward.
In order to prevent SQL injection, you should really use Prepared Statements, or correctly escape your strings. Please look at MySQLi or PDO.
Here's a basic tutorial using PDO and Prepared Statements inside of PHP:
// Connect to the database:
$db = new PDO( 'mysql:dbname=DB_NAME;host=localhost', 'DB_USER', 'DB_PASS' );
// Prepare the statement:
$ins = $db->prepare( 'INSERT INTO `formel` (`Område`, `Værelse`, `Dato`, `TV Fjernsyn Forlænger`) VALUES (:area, :filnavn, :dato, :Fjernsyn' );
// Execute with bindings:
$ins->execute(array(
':area' => $area,
':filnavn' => $filnavn,
':dato' => $dato,
':Fjernsyn' => $Fjernsyn
));
Try This,
$sql = "INSERT INTO `formel`(`Område`, `Værelse`, `Dato`, `TV Fjernsyn Forlænger`) VALUES ('$area','$filnavn','$dato','$Fjernsyn') ";
I think it should work.
Change your query to this
$sql = "INSERT INTO formel(Område, Værelse, Dato, TV Fjernsyn Forlænger) VALUES ('$area','$filnavn', '$dato', '$Fjernsyn') ";
But I would suggest you use prepared statement for security purposes
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I'm using this method to connect to my MySQL db to SELECT, INSERT, UPDATE and DELETE data. This is the cnn() function:
function cnn() {
static $pdo;
if(!isset($pdo)) {
$settings = [
PDO::ATTR_TIMEOUT => 30,
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
];
try {
# settings
$config['db']['host'] = 'example.com';
$config['db']['name'] = 'db';
$config['db']['user'] = 'username';
$config['db']['pass'] = '****************';
$pdo = new PDO('mysql:host='.$config['db']['host'].';dbname='.$config['db']['name'], $config['db']['user'], $config['db']['pass'], $settings);
return $pdo;
} catch(PDOException $e) {
http_response_code(503);
echo $e->getCode().': '.$e->getMessage();
}
} else {
return $pdo;
}
}
And then i can just do this to re-use the same pdo object each time i need it on the same request.
1st query
$sql = 'INSERT INTO user (name, lastname) VALUES (:name, :lastname)';
$stmt = cnn()->prepare($sql);
$stmt->bindValue(':name', "John", PDO::PARAM_STR);
$stmt->bindValue(':name', "Wayne", PDO::PARAM_STR);
$stmt->execute();
2nd query
$sql = 'SELECT * FROM user WHERE id_user = :id_user';
$stmt = cnn()->prepare($sql);
$stmt->bindValue(':id_user', 4641, PDO::PARAM_INT);
$stmt->execute();
$user = $stmt->fetch();
I was wondering if there could be any performance issues by using this approach. Thanks.
1)
As referenced by HTMHell, your $config array is local here and I believe this should be deleted after use so password variables are not leakable on a later get_defined_vars() call, or similar cross reference.
2)
It seems far more logical to me to put your function in a class. Run the cnn() function from the __construct. There are a lot of positive aspects to wrapping this function in a full class.
3)
Do NOT set any variable to being static unless you have a specific requirement in the context of putting your cnn() function into a Class.
4)
Correctly use your try{ ... } catch { ... } blocks, do not wrap other code in the try block except code that throws exceptions.
// settings
$config['db']['host'] = 'example.com';
$config['db']['name'] = 'db';
$config['db']['user'] = 'username';
$config['db']['pass'] = '****************';
try {
$pdo = new PDO('mysql:host='.$config['db']['host'].';dbname='.$config['db']['name'], $config['db']['user'], $config['db']['pass'], $settings);
} catch(PDOException $e) {
/***
* Do you really need this, here?
* //http_response_code(503);
**/
echo $e->getCode().': '.$e->getMessage();
}
return $pdo;
5)
DO NOT EVER OUTPUT ERRORS DIRECTLY TO THE SCREEN
Errors should be logged so only server folks and developers rather than the general public can see them. This also means you have a log of errors rather than a single, temporary instance of any that occur.
echo $e->getCode().': '.$e->getMessage(); Should be:
error_log($e->getCode().': '.$e->getMessage());
Or similar. Stay consistent; always return a PDO object and not echo outputs.
6)
Remove your final else wrapper it is merely clutter.
if(!isset($pdo)) {
...
}
return $pdo;
Also remove the return $pdo; inside your try { ... } block. Don't Repeat Yourself.
7)
Properly document your code:
/***
* For generating or asserting a PDO Database Object.
* #return Returns the PDO object
***/
function cnn() {
To answer the question you actually asked:
I was wondering if there could be any performance issues by using this approach.
This question is far too broad and can be solved by yourself using timer testings or other methods (detailed in the link) to establish on your system if it is particularly efficient or inefficient, or what SQL you choose to give it...
I'm struggling to make the jump form Procedural to Object Orientated style so if my code is untidy or flawed please be nice - here I'm passing a couple of posts via jQuery to a class to update a record when the user checks a checkbox:
Here is the database connection
class db {
private $host ;
private $username;
private $password;
private $dbname;
protected function conn()
{
$this->host = "localhost";
$this->username = "root";
$this->password = "";
$this->dbname = "mytest";
$db = new mysqli($this->host, $this->username, $this->password, $this->dbname);
if($db->connect_errno > 0){
die('Unable to connect to database [' . $db->connect_error . ']');
}
return $db;
}
}
Here is the update class
class updOrders extends db {
public $pid;
public $proc;
public function __construct()
{
$this->pid = isset($_POST['pid']) ? $_POST['pid'] : 0;
$this->proc = isset($_POST['proc']) ? $_POST['proc'] : 1;
// $stmt = $this->conn()->query("UPDATE tblorderhdr SET completed = ".$this->proc." WHERE orderid = ".$this->pid);
$stmt = $this->conn()->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
$stmt->bind_param('ii', $this->proc, $this->pid);
$stmt->execute();
if($stmt->error)
{
$err = $stmt->error ;
} else {
$err = 'ok';
}
/* close statement */
$stmt->close();
echo json_encode($err);
}
}
$test = new updOrders;
When I comment out the prepare statement and run the query directly (commented out) it updates, when I try and run it as a prepare statement it returns an error "MySQL server has gone away".
I have looked at your code and I found this.
$stmt = $this->conn()->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
I wrote nearly the same. But I saw you separated the connection from the prepare function.
$db = $this->conn();
$stmt = $db->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
I don't know either why, but it works now.
It would appear that the problem lies within the connection to the database. Here is the (relevant bit of the) updated code:
$db = $this->conn();
$stmt = $db->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
$stmt->bind_param('ii', $this->proc, $this->pid);
$stmt->execute();
When you call $this->conn(), you are creating a new connection object of class mysqli. When no more variables point to the object, PHP will trigger its destructor. The destructor for mysqli will close the connection. This means that if you do not save the return value of this method into a variable, there will be no more references pointing to the object and the connection will be closed.
To fix this, simply save the object and reuse it. Don't connect each time.
$conn = $this->conn();
$stmt = $conn->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
On a side note, creating a class like the one you have db is absolutely pointless. This class doesn't do anything useful. You haven't added any extra functionality to mysqli. You never need to save the credentials in properties. The whole class can be replaced with this code:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'password', 'test');
$mysqli->set_charset('utf8mb4'); // always set the charset
Then your classes will expect the mysqli object as a dependency.
class updOrders {
public $pid;
public $proc;
public function __construct(mysqli $conn) {
}
I need to do continuous parsing of several external stomp data streams, inserts of relevant fields into a MySql db, and regular queries from the db. All of this is in a protected environment - ie I'm not dealing with web forms or user inputs
Because I'm implementing a range of inserts into + queries from different tables, I've decided to set up a PDO active record model - following the advice of Nicholas Huot and many SO contributors.
I've got a simple repeated insert working OK, but after several days of grief can't get a prepared insert to fly. I want to use prepared inserts given there are going to be a lot of these (ie for performance).
Relevant bits of the code are :
=========
Database class :
private function __construct()
{
try {
// Some extra bad whitespace removed around =
$this->dbo = new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPSW, $options);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
public static function getInstance()
{
if(!self::$instance)
{
self::$instance = new self();
}
return self::$instance;
}
public function prepQuery($sql) // prepared statements
{
try {
$dbo = database::getInstance();
$stmt = new PDOStatement();
$dbo->stmt = $this->$dbo->prepare($sql);
var_dump($dbo);
}
catch (PDOException $e) {
echo "PDO prepare failed : ".$e->getMessage();
}
}
public function execQuery($sql) // nb uses PDO execute
{
try {
$this->results = $this->dbo->execute($sql);
}
catch (PDOException $e) {
echo "PDO prepared Execute failed : \n";
var_dump(PDOException);
}
}
=========
Table class :
function storeprep() // prepares write to db. NB prep returns PDOstatement
{
$dbo = database::getInstance();
$sql = $this->buildQuery('storeprep');
$dbo->prepQuery($sql);
return $sql;
}
function storexecute($paramstring) // finalises write to db :
{
echo "\nExecuting with string : " . $paramstring . "\n";
$dbo = database::getInstance(); // Second getInstance needed ?
$dbo->execQuery(array($paramstring));
}
//table class also includes buildQuery function which returns $sql string - tested ok
=======
Controller :
$dbo = database::getInstance();
$movements = new trainmovts();
$stmt = $movements->storeprep(); // set up prepared query
After these initial steps, the Controller runs through a continuous loop, selects the fields needed for storage into a parameter array $exec, then calls $movements->storexecute($exec);
My immediate problem is that I get the error message "Catchable fatal error: Object of class database could not be converted to string " at the Database prepquery function (which is called by the Table storeprep fn)
Can anyone advise on this immediate prob, whether the subsequent repeated executes should work in this way, and more widely should I change anything with the structure ?
I think your problem in this line $dbo->stmt = $this->$dbo->prepare($sql);, php want to translate $dbo to string and call function with this name from this. Actually you need to use $this->dbo.
And actually your functions not static, so i think you don't need to call getInstance each time, you can use $this.
this is my current Database class:
class Database {
private $db;
function Connect() {
$db_host = "localhost";
$db_name = "database1";
$db_user = "root";
$db_pass = "root";
try {
$this->db = new PDO("mysql:host=" . $db_host . ";dbname=" . $db_name, $db_user, $db_pass);
} catch(PDOException $e) {
die($e);
}
}
public function getColumn($tableName, $unknownColumnName, $columnOneName, $columnOneValue, $columnTwoName = "1", $columnTwoValue = "1") {
$stmt = $this->db->query("SELECT $tableName FROM $unknownColumnName WHERE $columnOneName='$columnOneValue' AND $columnTwoName='$columnTwoValue'");
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results[0][$unknownColumnName];
}
}
I'm trying to run it using the following code:
$db = new Database();
$db->Connect();
echo $db->getColumn("Sessions", "token", "uid", 1);
And i get the following error:
PHP Fatal error: Call to a member function fetchAll() on a non-object in /Users/RETRACTED/RETRACTED/root/includes/Database.php on line 19
Any idea what's up? Thanks
This function is prone to SQL injection.
This function won't let you get a column using even simplest OR condition.
This function makes unreadable gibberish out of almost natural English of SQL language.
Look, you even spoiled yourself writing this very function. How do you suppose it to be used for the every day coding? As a matter of fact, this function makes your experience harder than with raw PDO - you have to learn all the new syntax, numerous exceptions and last-minute corrections.
Please, turn back to raw PDO!
Let me show you the right way
public function getColumn($sql, $params)
{
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
return $stmt->fetchColumn();
}
used like this
echo $db->getColumn("SELECT token FROM Sessions WHERE uid = ?", array(1));
This way you'll be able to use the full power of SQL not limited to a silly subset, as well as security of prepared statements, yet keep your code comprehensible.
While calling it still in one line - which was your initial (and extremely proper!) intention.
it means your $stmt variable is not returning a PDOStatement object. your query is failing since PDO::query either returns a PDOStatement or False on error.
Use fetch instead of fetchAll..that will be easy in your case
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results[0][$unknownColumnName];
It will be
$results = $stmt->fetch(PDO::FETCH_ASSOC);
return $results[$unknownColumnName];
I have a question regarding the following Code. It's a PHP-Class which I plan to use as a DB-Handler. For the INSERT I'm using a little helper function, mainly because I'm too lazy to sanitize the strings from hand. Here is the Code:
<?php
class Db{
/*
* Configure DB settings here, make sure php is in good health. Check phpinfo();
*/
private $MYSQL_HOST = 'localhost';
private $MYSQL_USER = 'root';
private $MYSQL_PASS = '******';
private $db;
function select($selected_db, $sql){
//Create new object out of connection to db
$this->db = #new mysqli($this->MYSQL_HOST, $this->MYSQL_USER, $this->MYSQL_PASS, $selected_db);
//If there aren't any errors
if(mysqli_connect_errno() == 0){
$result = $this->db->query($sql);
if($result){
$result = $result->fetch_array(MYSQLI_ASSOC);
}else{
echo "There is a problem with the query";
}
} else { //If you couldn't connect to DB at all
die("No connection possible: " . mysqli_connect_error());
}
//Close connection
$this->db->close();
return $result;
}
function dirtyLittleHelper($string){
//Change each character into its HTML equivalent
$string = htmlentities($string);
//Create a legal SQL string from input
$string = $this->db->mysqli_real_escape_string($string);
return $string;
}
}
?>
Now for the error I get:
Fatal error: Call to a member function mysqli_real_escape_string() on a non-object in /path/to/file/db_class.php on line 35
The Question is simply why? I don't want to use the strings unsanitized and I don't want to use mysql_real_escape_string since it's deprecated.
Since this is my first time working with SQL, I'm taking the risk to post a duplicate of a question. It is important for me to learn it proper and not just use a version that works, leaving ways in to the database open.
Thanks in advance,
stiller_leser
EDIT
Thanks, I guess I'm going with elusive's hint. I did not know, that it prepare does that. Anyway just to check, a proper insert-function could look like that right?
function insert($selected_db, $sql){
//Create new object out of connection to db
$this->db = #new mysqli($this->MYSQL_HOST, $this->MYSQL_USER, $this->MYSQL_PASS, $selected_db);
//If there aren't any errors
if(mysqli_connect_errno() == 0){
//If you could prepare query
if($result = $db->prepare( $sql )){
//Execute query
$result->execute();
} else { //If you couldn't prepare query
echo "There is a problem with the query";
}
} else { //If you couldn't connect to DB at all
die("No connection possible: " . mysqli_connect_error());
}
//Close connection
$this->db->close();
The call should instead be like this
$string = $this->db->real_escape_string($string);
Please check the documentation.
Alternative solution would be:
$string = mysqli_real_escape_string($this->db, $string);
Your class seems inconsistent and unusable to me.
You are passing $selected_db to your functions, but never use it
instead of that you are creating a new connection for the every query you run(!)
there is no use for that little helper function can be seen.
and I suspect it's still unusable and unsafe anyway
calling prepare/execute doesn't protect your queries by itself. it have to be fed with variables to be bound to do any good
binding variables in mysqli is A PAIN
that's why you've been told to use PDO
Also, with adequately implemented placeholders, you won't need no special functions like delete(). update() and such, using conventional query() method to run them all queries:
$data = array('name' => 'John','surname'=>'doe', ...);
$db->query("INSERT INTO ?n SET ?u", $table, $data);
So, if you need PHP-Class to use as a DB-Handler, here is a SafeMysql which is written with some knowledge and experience