Should a semicolon be included when building SQL query - php

When I access mysql from PHP (Joomla) application. Should I include semicolon in SQL queries I send? I.e.
$db->setQuery("SELECT * FROM `blah`;");
or
$db->setQuery("SELECT * FROM `blah`");
It might be a case of splitting hairs, but I want to do it consistently - might as well choose a way that is significantly or insignificantly better.
NOTE: Joomla platform code does not include semicolons in queries. But I don't trust it.
UPDATE: I understand that it works both with and without the semicolon, I am asking if there are any advantages of one way vs the other (except without semicolon being one character shorter).

Semicolons are primarily used to separate multiple queries when dealing with SQL, so no, you do not need to provide a semi-colon.

I am going to assume that the setQuery() function is storing these SQL statements individually in an array rather than creating a concatenated string which would run all at once so in this case you do not need semi-colons. You would probably break the matrix trying to run two SELECTs like that.
I can see semi-colons as becoming useful when you want to INSERT many rows into a DB and don't want to call execute() thousands of times but then again this syntax would work for that:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
I have primarily used semi-colons when running a sequence of queries in the MySQL Workbench because the cursor needs to be somewhere inside the query you wish to run upon clicking that little execute lightning bolt thingy.

No Semicolons required just the queries will be working fine.

Related

PDO lastInsertID() failing due to running multiple queries in a single call

This is odd. I'm running a query with just a single INSERT, preceded by a SET statement. The query looks something like this:
SET #discount:=(SELECT discount * :applyDiscount FROM fra_cus WHERE customerID=:customerID AND franchiseID=:franchiseID);
INSERT INTO discounts_applied (unitID, franchiseID, customerID, amount)
VALUES(:unitID, :franchiseID, :customerID, #discount * :price);
It appears that if I prepare these as two separate PDO queries, lastInsertID() works fine... but if I prepare them and execute them in the same statement, lastInsertID() returns nothing.
It's not the end of the world, but it's annoying. Anyone know why this would be the case? For the record, there's a reason I need to define #discount as a variable (pertains to triggers on one of the tables). Also this is all taking place within a larger transaction.
First of all, I would strongly recommend to run every query in a distinct API call. This is how an Application Programming Interface is intended to work.
It won't only prevent situations like this but also will make your code a multitude times more readable and maintainable.
And it will make your code much safer too. You can run multiple statements in a single call only at the expense of the native prepared statements. However virtual this vulnerability is, why taking chances at all?
Why not to make a regular SELECT query instead of SET, get the resulting value into a PHP variable and then use it among other variables, just through a placeholder? I don't see any reason why there should be such a complex way to deal with simple data.
In case I failed to convince you, the reason is simple. You are running two queries, and the first one doesn't trigger any insert ids. And obviously, you need this query's metadata (errors, affected rows, whatever), not the other one's first. So you get it. And to get the second'query's metadata you have to ask a database for it. The process is explained in my article: Treating PHP delusions - The only proper PDO tutorial: Running multiple queries with PDO. Basically PDOStatement::nextRowset() is what you need.

Multiple queries in code igniter - semicolon breaks query

I am working on a project where I need to create a pivot table with dynamic columns. To this end I am using the tutorial as described here: http://stratosprovatopoulos.com/web-development/mysql/pivot-table-with-dynamic-columns/
Using that tutorial, I was able to make a proper query to make a pivot table.
When I execute it via phpMyAdmin SQL dialog, the query runs fine and the results come up as expected. The problem I ran into is that when I try to run the query through Code Igniter via $this->db->query($query), it fails at the first semicolons that mark the end of the first SQL statement in the overall query. The problem is that the statement is built up of several queries that I need to run at the same time.
I read about transactions on CI, but could not figure how (if possible) to obtain the result of the query.
Will greatly appreciate any advice on a proper way to run that query on CI and avoid the semicolon problem.
Thanks!
In case this is helpful to anyone in the future, I was able to get over the multi-statement issue by placing the whole query inside a stored procedure. The procedure along with its parameters is then called via CodeIgniter.

Multiple prepared statements, keep alive until finish page

Lets say a have Web page with some classes. One is loaded Mysqli connect it to DB at the beginning and keep connected. Now question is:
Is good solution make in (example setting class) prepared statement for calling value from DB table 'settings' and keep it open (statement) until finish (at footer close statement and connection) or just load all data from 'settings' DB table to array() in php and just call it from array not binding it from DB.
Second question is if I have statement open may I open another statement for another class (example class for calling text from DB) and do it same like in previous example? And than, of course close it at finish page.
Is there any performance or security problem, you can see there...
As far as I know, nobody is doing it this way. Mostly because the real benefit from the multiple execution is not that grand as some imagine, and just doesn't worth the trouble. For the short primary key lookups run in small numbers (several dozens at max) you'll hardly be able to tell the difference.
(However, there are no arguments against such practice either - you can make it this way, with single statement prepared/multiple executions, if you wish).
Yet single query that is fetching no more than couple hundreds of records still would be faster than separate queries (even prepared) to get the same amount. So, as long as your settings keep at moderate amount, it's better to get them all at once.
Yes, of course you can have as many statements prepared as you need.
(The only problem could be with fetching results. You have to always get_result/store_result, to make sure there are no results left pending and preventing other queries to run, either regular or prepared).
The statement executes as one SQL statement over your DB connection. It's not going to keep going back to the database and grabbing a single row one at a time, so don't worry about that.
In general, you should be loading everything into some data structure. If your query is returning more data than you need, then that's something you need to fix in your query. Don't run SQL that returns a huge set of data, then rely on PHP to go through it row by row and perform some hefty operations on it. Just write SQL that gets what you need in the first place. I realize this isn't always possible, but when people talk about optimizing their website, query optimization is usually at/near the top of that list, so it's pretty important.
You're definitely supposed to execute multiple statements. It's silly to keep opening and closing entire db connections before getting any data.

What's the safest way to write loads of data / SQL to a text file?

I'm facing an issue with query / data integrity.
I'm reading loads of data (many gigabytes) from a MySQL database, processing them using PHP, to re-insert them into the same database in completely different tables. It's a one-run conversion from an old data structure to a new one, where tons of values need on the fly modification.
SELECT FROM x -> modify in PHP -> INSERT INTO y is way too slow. That takes around 1 second per 1000 records, and we're talking many many millions here. That's why I decided to export every INSERT into a text/sql file.
But, what's the safest way to go here? The data is everything from booleans to BLOB's. I can't really be sure of what's in it and what's not, but everything needs to get back into place appropriately, including quotes, slashes, etc.
How can I escape without any data loss?
You can use prepared statements to avoid the need to escape the data.
The queries you create for the prepared statements can be concatenated and executed as a group, instead of having one execute call for each row.
The code that creates, groups & concatenates SQL statements together should allow you to easily choose the number of statements concatenated in a group so you can experiment with 100 statements in one exec call vs. 1000 statements in one exec call.
The results should be much better.

MySQL query is creating a duplicate row

I have never encountered an error like this before. I was using prepared statements when it stared and have tried everything to correct the problem including stripping the form down to it's bare components.
The following code, when executed, is creating a duplicate row.
$sql = "INSERT INTO inventory
VALUES ('','$stocknum','$year','$make','$model','$price','$body','$mile','$engine','$trans',
'$drive','$doors','$fuel','$vin','$des','$featured','$sale','$features','$safety','$airbags','$power',
'$exterior','$interior','','','','','')";
$insert = mysql_query($sql,$connection) or die(mysql_error());
$name = mysql_insert_id();
I can't wrap my head around why it would do this.
I had the same problem in a project while using and orm library to access to the database. Also tried tested with mysql directly
After almost one day testing in multiple browsers and getting diferente results, i've found out that the extensions that i used (Webug) for Chrome caused tha recall to the page. After disabling the extension, it worked
I've tested some extensions that caused that problem... In chrome: Webug.
Hope it helps
The insert statement is possibly getting called twice. Did you add logging to make sure this code is only running once? And did you search to make sure there's no other code to add inventory records anywhere else?
How many columns are in the inventory table? Is the second row an exact duplicate of the first? I don't know PHP's DB interface but I could envision a bug where, if you give it more fields than there are columns, it attempts to create multiple rows.
EDIT: A little research on the MySQL documentation finds:
INSERT statements that use VALUES
syntax can insert multiple rows. To do
this, include multiple lists of column
values, each enclosed within
parentheses and separated by commas.
Example:
INSERT INTO tbl_name (a,b,c)
VALUES(1,2,3),(4,5,6),(7,8,9);
The values list for each row must be
enclosed within parentheses. The
following statement is illegal because
the number of values in the list does
not match the number of column names:
INSERT INTO tbl_name (a,b,c)
VALUES(1,2,3,4,5,6,7,8,9);
Depending on the contents of your variables and how the PHP/MySQL driver handles those variables (direct text substition or ? placeholders) the statement being executed may not look like you expect. Try displaying the value of $sql before you execute it.
When you query the table afterwards, are you only selecting from this table or are you perhaps joining it to another table? If you have more than one child record in the joined table you will get multiple results.
Your code looks correct to me, unless there is something in the rest of the page I'm not seeing.
In the absence of any real clear conclusion on this my observation is that I think Red Element is on the right track when he states 'I think it has something to do with my web host as now every script that adds SQL data is doing the same thing'.
I had the problem outlined above and could not see what on earth caused this until I ran the same code on a different platform and it worked fine. I was originally testing in a localhost WAMP configuration but when I promoted the code to a real server, it worked no problem.
Therefore I suggest that if anyone else has the problem it is worth a try on a different server config.
I'd guess you have a problem with an .htaccess file which is making 2 requests to the same script. Log a message with a timestamp when you do your insert.

Categories