I am trying to insert a big file (few millions row) via SQL server BULK INSERT functionality. My SQL query will look like:
BULK INSERT MY_TABLE
FROM '\\myserver\open\myfile.csv'
WITH (
firstrow=2,
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
BATCHSIZE = 50000,
ERRORFILE = '\\myserver\open\myfileerror.log'
);
When I trigger it from MSSQL Server Management Studio, it always import it completely.
When I do it from my PHP code, sometimes it stop in the middle, without any error messages.
I tried with both sqlsrv_query or sqlsrv_prepare/sqlsrv_execute, same result.
sql; //like the query above
$statement = sqlsrv_query($connection, $sql);
if($statement === false) {
$error = sqlsrv_errors();
$error['sql'] = $sql;
throw new Exception(json_encode($error));
}
Would it be possible to get the logs of MSSQL from the $statement, the same I get from the MSSQL Studio? e.g. (50000 row(s) affected).
As a workaround, I have increased the BATCHSIZE to 1000000, but that is not a real solution.
Background information:
- PHP 7.1.9
- sqlsrv version: 4.3.0+9904
- sqlsrv.ClientBufferMaxKBSize: 10240
- Windows 2012 R2 Server
The issue was about the statement buffer. When I read it with sqlsrv_next_result, processing continue.
$statement = sqlsrv_query($connection, $sql);
if($statement === false) {
$error = sqlsrv_errors();
$error['sql'] = $sql;
throw new Exception(json_encode($error));
} else if($statement) {
while($next_result = sqlsrv_next_result($statement)){
#echo date("Y-m-d H:i:s",time()). " Reading buffer...\n";
}
}
Related
a new webserver has been stood up for me. It is Ubuntu 20.04 and has PHP 7.4.3 on it. I am working with MS SQL Server 2012. I can send my SQL query to the DB server and see it in SQL Server Profiler. I can copy it from the profiler and it runs fine in SQL Management Studio but, I am having a problem when I try to echo the results to my page. When I use sqlsrv_num_rows I get -1. Could I get a hand please?
<?php
if(isset($_POST['getPassBtn'])){
#DATABASE LOGIN
include './php/inc/dbLogin/mydb.php';
#FORM POST VARIABLES
$badge = $_POST['empId'];
//$badge = (int)$badge;
#check badge entry for paramiters
if($badge == '' || $badge < 10000 || $badge > 30000){
echo '<br/> ERROR : Invalid Badge Number <br/>';
die();
}
$sql = "USE mydb SET NOCOUNT ON SELECT badgeNumber, userPassword FROM dbo.users WHERE badgeNumber = '$badge' ORDER BY badgeNumber ASC --getTestData.php";
//$sql = "USE toolsMeskwaki SELECT * FROM bingoProgressive.users ORDER BY badgeNumber ASC --getTestData.php";
$params = array();
$options = array( 'Scrollable' => 'buffered');
$stmt = sqlsrv_query( $conn, $sql, $params, $options);
#check if query returns false
if( $stmt === false ) {
die( print_r( sqlsrv_errors(), true));
}else{
echo '<br/> Query sent to SQL Server <br/>';
}
/*
$row_count = sqlsrv_num_rows( $stmt );
if ($row_count === false){
echo "Error in retrieveing row count.";
}else{
echo $row_count;
}
*/
#Fetching Data by array
while($row = sqlsrv_fetch_array($stmt)){
echo 'badgeNumber '.$row['badgeNumber'];
echo 'userPassword '.$row['userPassword'];
}
#release query
sqlsrv_free_stmt($stmt);
#CLOSE DATA BASE CONNECTION
sqlsrv_close($conn);
echo "<br/> SQL Server Connection closed.<br />";
}else{
echo '<br/> click GET btn to connect SQL Server <br/>';
}
?>
You're submitting three different statements:
USE mydb
SET NOCOUNT ON
SELECT badgeNumber, userPassword FROM dbo.users WHERE badgeNumber = '$badge' ORDER BY badgeNumber ASC
It works in SQL Management Studio for two reasons:
Auto-magic statement detection, although deprecated for several years (you're now expected to use ; as delimiter), is still supported.
The query tool is specifically designed to run several statements at once.
We know that sqlsrv_query() supports it because it isn't returning false. But, given that you're running three statements, you need you use sqlsrv_next_result() twice to move to the third result set.
On a side note:
You can use sqlsrv_connect() to provide the initial database. You only need to switch DBs if you use several of them and you don't want to add the name as mydb.dbo.users.
SQLSRV supports prepared statements (see sqlsrv_prepare() and sqlsrv_execute()).
I am generating a SQL insert statement within a PHP for loop.
The SQL string generated is a large number of individual SQL statements like this:
INSERT INTO tbl VALUES(1,2,3);
INSERT INTO tbl VALUES(4,5,6);
INSERT INTO tbl VALUES(7,8,9);
etc...
Then I execute with:
$InsertResult = sqlsrv_query($conn, $InsertSQL);
The problem is that only the first 312 statements get executed instead of the full 2082 lines (only 312 rows are inserted into the table).
When I output the $InsertSQL variable to the JavaScript console and then execute it manually in SSMS it works perfectly and inserts all 2082 lines. Only when I run the $InsertSQL variable through sqlsrv_query does it not go to completion.
I also don't get any errors and the query result comes back true as tested in this line:
if(!$InsertResult) die('Problem with Insert query: ' . $InsertSQL);
When I searched for a solution to this problem I saw that (although it's not mentioned in the PHP manual site) sqlsrv_query apparently has a string character limit on the $SQL variable (around 65k characters).
See the other StackOverflow article here:
length restriction for the sql variable on sqlsrv_query?
I figured this was the problem and so created a shorter version of the string (by only adding in the column values that I actually wanted to import). This much shorter version however, still only Inserts the first 312 lines! So now it seems this is NOT related to the max string length. In fact, if it was, I should only get around 250 lines (after 250 statements I'm at about 65k characters).
I can also execute each insert statement individually but of course this takes much longer. In my testing, it takes 90s or so to do it this way where as running the combined statement manually in SMSS takes only around 40s.
Note that I've also looked into SQL Server's Bulk Insert however I won't be able to send the file to the machine where SQL Server is installed (SQL Server and Web servers are on separate computers). From my understanding this eliminates this possibility.
Any help is much appreciated as I can't even figure out what it is that is limiting me, never mind fix it and I'd hate to have to execute one line at a time.
Explanations:
There is a known issue with this driver, posted on GitHub, about executing large SQL statements. One part of the provided solution are the following explanations:
Seems like when executing a large batch of SQL statements, Microsoft SQL Server may stop processing the batch before all statements in the batch are executed. When processing the results of a batch, SQL Server fills the output buffer of the connection with the result sets that are created by the batch. These result sets must be processed by the client application. If you are executing a large batch with multiple result sets, SQL Server fills that output buffer until it hits an internal limit and cannot continue to process more result sets. At that point, control returns to the client. This behavior is by design.
Client app should flush all the pending result sets. As soon as all pending result sets are consumed by the client, SQL Server completes executing the batch. Client app can call sqlsrv_next_result() until it returns NULL.
So, I don't think that there is a limit for the SQL statement length, only the size of a PHP string variable ($InsertSQL in your case) is limited to the maximum allowed PHP memory limit. The actual reason for this unexpected behaviour is the fact, that with SET NOCOUNT OFF (this is by default) and a large number of single INSERT statements, the SQL Server returns the count of the affected rows as a result set (e.g. (1 row affected)).
Solution:
I'm able to reprodiuce this issue (using SQL Server 2012, PHP 7.1.12 and PHP Driver for SQL Server 4.3.0+9904) and you have the following options to solve this problem:
Flush the pending result sets using sqlsrv_next_result().
Execute SET NOCOUNT ON as first line in your complex T-SQL statement to stop SQL Server to return the count of the affected rows as a resultset.
Use parameterized statement using sqlsrv_prepare()\sqlsrv_execute()
Table:
CREATE TABLE MyTable (
Column1 int,
Column2 int,
Column3 int
)
One complex statement (using sqlsrv_query() and sqlsrv_next_result()):
<?php
// Connection info
$server = 'server\instance';
$database = 'database';
$username = 'username';
$password = 'password';
$cinfo = array(
"Database" => $database,
"UID" => $username,
"PWD" => $password
);
// Statement with sqlsrv_query
$sql = "";
for ($i = 1; $i <= 1000; $i++) {
$sql .= "INSERT INTO MyTable (Column1, Column2, Column3) VALUES (".$i.", 0, 0);";
}
$stmt = sqlsrv_query($con, $sql);
if ($stmt === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
// Clean the buffer
while (sqlsrv_next_result($stmt) != null){};
// End
sqlsrv_free_stmt($stmt);
sqlsrv_close($con);
echo "OK";
?>
One complex statement (using sqlsrv_query() and SET NOCOUNT ON):
<?php
// Connection info
$server = 'server\instance';
$database = 'database';
$username = 'username';
$password = 'password';
$cinfo = array(
"Database" => $database,
"UID" => $username,
"PWD" => $password
);
// Connection
$con = sqlsrv_connect($server, $cinfo);
if ($con === false) {
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
// Statement with sqlsrv_query
$sql = "SET NOCOUNT ON;";
for ($i = 1; $i <= 1000; $i++) {
$sql .= "INSERT INTO MyTable (Column1, Column2, Column3) VALUES (".$i.", 0, 0);";
}
$stmt = sqlsrv_query($con, $sql);
if ($stmt === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
// End
sqlsrv_free_stmt($stmt);
sqlsrv_close($con);
echo "OK";
?>
Parameterized statement (using sqlsrv_prepare() and sqlsrv_execute()):
<?php
// Connection info
$server = 'server\instance';
$database = 'database';
$username = 'username';
$password = 'password';
$cinfo = array(
"Database" => $database,
"UID" => $username,
"PWD" => $password
);
// Connection
$con = sqlsrv_connect($server, $cinfo);
if ($con === false) {
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
$sql = "INSERT INTO MyTable (Column1, Column2, Column3) VALUES (?, ?, ?);";
$value1 = 0;
$value2 = 0;
$value3 = 0;
$params = array(&$value1, &$value2, &$value3);
$stmt = sqlsrv_prepare($con, $sql, $params);
if ($stmt === false ) {
echo "Error (sqlsrv_prepare): ".print_r(sqlsrv_errors(), true);
exit;
}
for ($i = 1; $i <= 1000; $i++) {
$value1 = $i;
$value2 = 0;
$value3 = 0;
$result = sqlsrv_execute($stmt);
if ($result === false) {
echo "Error (sqlsrv_execute): ".print_r(sqlsrv_errors(), true);
exit;
}
}
// End
sqlsrv_free_stmt($stmt);
sqlsrv_close($con);
echo "OK";
?>
I'm using php and postgresql+postgis to automatically remove nested shells from simplified geojson files, I'm also doing a similar query with pgadmin to get other errors and manually fix them. All is working as needed but the php script won't start correctly sometimes, after starting it just stays there (with no cpu usage on postgresql or php) and I have to restart the postgresql server so the php script can work again.
This is the sql I'm using on both pgadmin and php (query.txt):
CREATE OR REPLACE FUNCTION read_file_utf8(path CHARACTER VARYING)
RETURNS TEXT AS $$
DECLARE
var_file_oid OID;
var_record RECORD;
var_result BYTEA := '';
BEGIN
SELECT lo_import(path)
INTO var_file_oid;
FOR var_record IN (SELECT data
FROM pg_largeobject
WHERE loid = var_file_oid
ORDER BY pageno) LOOP
var_result = var_result || var_record.data;
END LOOP;
PERFORM lo_unlink(var_file_oid);
RETURN convert_from(var_result, 'utf8');
END;
$$ LANGUAGE plpgsql;
SELECT replace(
ST_IsValidReason(ST_GeomFromGeoJSON(
read_file_utf8('some_file.geojson')
)),
' ',
','
);
On php I'm running pg_query like this:
$query = file_get_contents('query.txt');
$dbc = pg_pconnect('host=localhost port=5432 dbname=XXX user=XXX password=XXX');
if (!pg_connection_busy($dbc)) {
$has_error = true;
while ($has_error) {
$res = pg_query($dbc, $query);
if ($row = pg_fetch_row($res)) {
if (!fix_json($row[0])) { $has_error = false; }
}
else { $has_error = false; }
}
}
pg_close();
When I restart the postgresql service I get this error on php:
Warning: pg_query(): Query failed: FATAL: terminating connection due to administrator command
CONTEXT: while updating tuple (180,4) in relation "pg_proc"
server closed the connection unexpectedly
I'm on windows 10 x64 1703, php x64 5.6.30, postgresql server x64 10.1
Below code runs without any problems on my local server. However, when I try to run it on the intended server, two of my queries don't work - they do not INSERT as they are supposed to. I've marked two queries that don't work with comments, the rest works. Intended server runs on PHP 5.6.30-0+deb8u1.
UPDATE: thanks to aynber, I've tracked the error. This is the error for the first query: prepared statement \"editRecord\" does not exist" I don't understand why this works on local server but not on intended one.
UPDATE 2: error between prepared statement and execution: syntax error at or near \"ON\"\nLINE 3:
case "editRecord":
$id = openPandoraBox(post("id"));
$tutorAbsence = post("tutorAbsence");
$clientAbsence = post("clientAbsence");
if($tutorAbsence == "1") {
if(post("tutor") != "0") {
// ------------this query does not work.-----------
$absUpsSql = "INSERT INTO tutorabsence(id, tutorid, reason)
VALUES ($1, $2, $3)
ON CONFLICT (id)
DO UPDATE SET tutorid=$2, reason=$3";
$absUpsPrep = pg_prepare($conn, 'editRecord', $absUpsSql);
$absUpsQry = pg_execute($conn, 'editRecord',
array($id, post("tutor"), post("tutorreason"))
);
} else {
$tutorAbsence = "0";
};
} else {
$absDelSql = "DELETE FROM tutorabsence WHERE id=$1";
$absDelPrep = pg_prepare($conn, 'absDel', $absDelSql);
$absDelQry = pg_execute($conn, 'absDel', array($id));
};
if($clientAbsence == "1"){
if(post("client") != "0") {
// ------------this query does not work.-----------
$absUpsSql = "INSERT INTO clientabsence(id, clientid, reason)
VALUES ($1, $2, $3)
ON CONFLICT (id)
DO UPDATE SET clientid=$2, reason=$3";
$absUpsPrep = pg_prepare($conn, 'absUps', $absUpsSql);
$absUpsQry = pg_execute($conn, 'absUps',
array($id, post("client"), post("clientreason"))
);
} else {
$clientAbsence = "0";
};
} else {
$absDelSql = "DELETE FROM clientabsence WHERE id=$1";
$absDelPrep = pg_prepare($conn, 'absDelOne', $absDelSql);
$absDelQry = pg_execute($conn, 'absDelOne', array($id));
};
$resultSql = "UPDATE appointments
SET hour=$1, tutorid=$2,
clientid=$3, purpose=$4,
tutornotshown=$5, clientnotshown=$6
WHERE appid=$7";
$resultPrep = pg_prepare($conn, 'resultSql', $resultSql);
$result = pg_execute($conn, 'resultSql',
array(post('hour'), post("tutor"), post("client"),
post("purpose"), $tutorAbsence, $clientAbsence, $id
)
);
echo json_encode(array("success" => 1));
break;
UPDATE 2: error between prepared statement and execution: syntax error at or near \"ON\"\nLINE 3:
If it works on your local server but not on production server, it is likely that they don't run the same version of PostgreSQL. ON CONFLICT is a feature that was released with PostgreSQL 9.5 (https://www.postgresql.org/docs/9.5/static/sql-insert.html) which is still fairly recent.
You should run this query on the production server to check out which version of PostgreSQL it uses:
SELECT version();
Your server probably runs PostgreSQL 9.5 or 9.6 while the production server is probably on an older release.
Upsert for PostgreSQL below 9.5 is too complicated. I am very short of time, so I'll just use SELECT COUNT(*) and if's.
I do know that PDO does not support multiple queries getting executed in one statement. I've been Googleing and found few posts talking about PDO_MYSQL and PDO_MYSQLND.
PDO_MySQL is a more dangerous
application than any other traditional
MySQL applications. Traditional MySQL
allows only a single SQL query. In
PDO_MySQL there is no such limitation,
but you risk to be injected with
multiple queries.
From: Protection against SQL Injection using PDO and Zend Framework (June 2010; by Julian)
It seems like PDO_MYSQL and PDO_MYSQLND do provide support for multiple queries, but I am not able to find more information about them. Were these projects discontinued? Is there any way now to run multiple queries using PDO.
As I know, PDO_MYSQLND replaced PDO_MYSQL in PHP 5.3. Confusing part is that name is still PDO_MYSQL. So now ND is default driver for MySQL+PDO.
Overall, to execute multiple queries at once you need:
PHP 5.3+
mysqlnd
Emulated prepared statements. Make sure PDO::ATTR_EMULATE_PREPARES is set to 1 (default). Alternatively you can avoid using prepared statements and use $pdo->exec directly.
Using exec
$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
// works regardless of statements emulation
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
$sql = "
DELETE FROM car;
INSERT INTO car(name, type) VALUES ('car1', 'coupe');
INSERT INTO car(name, type) VALUES ('car2', 'coupe');
";
$db->exec($sql);
Using statements
$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
// works not with the following set to 0. You can comment this line as 1 is default
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);
$sql = "
DELETE FROM car;
INSERT INTO car(name, type) VALUES ('car1', 'coupe');
INSERT INTO car(name, type) VALUES ('car2', 'coupe');
";
$stmt = $db->prepare($sql);
$stmt->execute();
A note:
When using emulated prepared statements, make sure you have set proper encoding (that reflects actual data encoding) in DSN (available since 5.3.6). Otherwise there can be a slight possibility for SQL injection if some odd encoding is used.
After half a day of fiddling with this, found out that PDO had a bug where...
--
//This would run as expected:
$pdo->exec("valid-stmt1; valid-stmt2;");
--
//This would error out, as expected:
$pdo->exec("non-sense; valid-stmt1;");
--
//Here is the bug:
$pdo->exec("valid-stmt1; non-sense; valid-stmt3;");
It would execute the "valid-stmt1;", stop on "non-sense;" and never throw an error. Will not run the "valid-stmt3;", return true and lie that everything ran good.
I would expect it to error out on the "non-sense;" but it doesn't.
Here is where I found this info:
Invalid PDO query does not return an error
Here is the bug:
https://bugs.php.net/bug.php?id=61613
So, I tried doing this with mysqli and haven't really found any solid answer on how it works so I thought I's just leave it here for those who want to use it..
try{
// db connection
$mysqli = new mysqli("host", "user" , "password", "database");
if($mysqli->connect_errno){
throw new Exception("Connection Failed: [".$mysqli->connect_errno. "] : ".$mysqli->connect_error );
exit();
}
// read file.
// This file has multiple sql statements.
$file_sql = file_get_contents("filename.sql");
if($file_sql == "null" || empty($file_sql) || strlen($file_sql) <= 0){
throw new Exception("File is empty. I wont run it..");
}
//run the sql file contents through the mysqli's multi_query function.
// here is where it gets complicated...
// if the first query has errors, here is where you get it.
$sqlFileResult = $mysqli->multi_query($file_sql);
// this returns false only if there are errros on first sql statement, it doesn't care about the rest of the sql statements.
$sqlCount = 1;
if( $sqlFileResult == false ){
throw new Exception("File: '".$fullpath."' , Query#[".$sqlCount."], [".$mysqli->errno."]: '".$mysqli->error."' }");
}
// so handle the errors on the subsequent statements like this.
// while I have more results. This will start from the second sql statement. The first statement errors are thrown above on the $mysqli->multi_query("SQL"); line
while($mysqli->more_results()){
$sqlCount++;
// load the next result set into mysqli's active buffer. if this fails the $mysqli->error, $mysqli->errno will have appropriate error info.
if($mysqli->next_result() == false){
throw new Exception("File: '".$fullpath."' , Query#[".$sqlCount."], Error No: [".$mysqli->errno."]: '".$mysqli->error."' }");
}
}
}
catch(Exception $e){
echo $e->getMessage(). " <pre>".$e->getTraceAsString()."</pre>";
}
A quick-and-dirty approach:
function exec_sql_from_file($path, PDO $pdo) {
if (! preg_match_all("/('(\\\\.|.)*?'|[^;])+/s", file_get_contents($path), $m))
return;
foreach ($m[0] as $sql) {
if (strlen(trim($sql)))
$pdo->exec($sql);
}
}
Splits at reasonable SQL statement end points. There is no error checking, no injection protection. Understand your use before using it. Personally, I use it for seeding raw migration files for integration testing.
Like thousands of people, I'm looking for this question:
Can run multiple queries simultaneously, and if there was one error, none would run
I went to this page everywhere
But although the friends here gave good answers, these answers were not good for my problem
So I wrote a function that works well and has almost no problem with sql Injection.
It might be helpful for those who are looking for similar questions so I put them here to use
function arrayOfQuerys($arrayQuery)
{
$mx = true;
$conn->beginTransaction();
try {
foreach ($arrayQuery AS $item) {
$stmt = $conn->prepare($item["query"]);
$stmt->execute($item["params"]);
$result = $stmt->rowCount();
if($result == 0)
$mx = false;
}
if($mx == true)
$conn->commit();
else
$conn->rollBack();
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}
return $mx;
}
for use(example):
$arrayQuery = Array(
Array(
"query" => "UPDATE test SET title = ? WHERE test.id = ?",
"params" => Array("aa1", 1)
),
Array(
"query" => "UPDATE test SET title = ? WHERE test.id = ?",
"params" => Array("bb1", 2)
)
);
arrayOfQuerys($arrayQuery);
and my connection:
try {
$options = array(
//For updates where newvalue = oldvalue PDOStatement::rowCount() returns zero. You can use this:
PDO::MYSQL_ATTR_FOUND_ROWS => true
);
$conn = new PDO("mysql:host=$servername;dbname=$database", $username, $password, $options);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo "Error connecting to SQL Server: " . $e->getMessage();
}
Note:
This solution helps you to run multiple statement together,
If an incorrect a statement occurs, it does not execute any other statement
PDO does support this (as of 2020). Just do a query() call on a PDO object as usual, separating queries by ; and then nextRowset() to step to the next SELECT result, if you have multiple. Resultsets will be in the same order as the queries. Obviously think about the security implications - so don't accept user supplied queries, use parameters, etc. I use it with queries generated by code for example.
$statement = $connection->query($query);
do {
$data[] = $statement->fetchAll(PDO::FETCH_ASSOC);
} while ($statement->nextRowset());
Try this function : multiple queries and multiple values insertion.
function employmentStatus($Status) {
$pdo = PDO2::getInstance();
$sql_parts = array();
for($i=0; $i<count($Status); $i++){
$sql_parts[] = "(:userID, :val$i)";
}
$requete = $pdo->dbh->prepare("DELETE FROM employment_status WHERE userid = :userID; INSERT INTO employment_status (userid, status) VALUES ".implode(",", $sql_parts));
$requete->bindParam(":userID", $_SESSION['userID'],PDO::PARAM_INT);
for($i=0; $i<count($Status); $i++){
$requete->bindParam(":val$i", $Status[$i],PDO::PARAM_STR);
}
if ($requete->execute()) {
return true;
}
return $requete->errorInfo();
}
Tried following code
$db = new PDO("mysql:host={$dbhost};dbname={$dbname};charset=utf8", $dbuser, $dbpass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
Then
try {
$db->query('SET NAMES gbk');
$stmt = $db->prepare('SELECT * FROM 2_1_paidused WHERE NumberRenamed = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));
}
catch (PDOException $e){
echo "DataBase Errorz: " .$e->getMessage() .'<br>';
}
catch (Exception $e) {
echo "General Errorz: ".$e->getMessage() .'<br>';
}
And got
DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 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 '/*' LIMIT 1' at line 1
If added $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); after $db = ...
Then got blank page
If instead SELECT tried DELETE, then in both cases got error like
DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 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 '* FROM 2_1_paidused WHERE NumberRenamed = '¿\' OR 1=1 /*' LIMIT 1' at line 1
So my conclusion that no injection possible...