I am trying to insert data into one of the 3 tables in a database using PDOs. When I call the insert function below, and get the error: SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected.
Probably going out on a limb here.
It seems to me that you haven't created any of the variables/arrays for your connection, or is not configured correctly. (Not enough code posted in your question).
From the manual on PDO connection http://php.net/manual/en/pdo.connections.php
Example #1 Connecting to MySQL
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
?>
Example #2 Handling connection errors
<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
foreach($dbh->query('SELECT * from FOO') as $row) {
print_r($row);
}
$dbh = null;
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
?>
Plus, looking at the "image of" your code, it looks to me like you are using regular quotes around your columns, rather than ticks. Those are two different animals altogether.
INSERT INTO Students ('RIN', 'First Name', 'Last Name' ...
and having spaces between words, where yes; ticks must be used.
Therefore, you need to modify your code to read as
INSERT INTO Students (`RIN`, `First Name`, `Last Name` ...
and changing the quotes to ticks as outlined above for all the other column names. I wasn't going to type everything out here.
You also need to check for errors with exceptions in the DSN. Using what you have now, isn't enough.
http://php.net/manual/en/pdo.error-handling.php
Example #1 Create a PDO instance and set the error mode
<?php
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
try {
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
?>
Make sure that you chose (and created) the right database/table and that you did in fact create all those columns and using the right types and lengths.
If you get errors for something that MySQL may complain about (such as apostrophes), then you will need to escape your data; something you should be doing anyway.
Consult the following, and use a prepared statement:
http://php.net/manual/en/pdo.prepared-statements.php
In your code I didn't see where or when you selected the db. see this for more info.
But to be clear this is what I', referring to
$conn = new mysqli($servername, $username, $password, $dbname);
as you can see the last variable is the dbname.
Related
What is the proper way to "encapsulate" the sql queries scripts and connection script with try/catch or if/else blocks? I want to have a config.php file that will contain the connection part:
<?php
$servername = "localhost";
$username = "username";
$password = "password";
try {
$conn = new PDO("mysql:host=$servername;dbname=myDB", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
?>
Now taken from w3schools, when they insert a value to the database, they simply re-write the entire connection part again:
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', 'john#example.com')";
// use exec() because no results are returned
$conn->exec($sql);
echo "New record created successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
but I want to properly separate the two. Also, if I use prepared statements, do I need to check if on each part? i.e the prepare, bindParam and execute? Or a single try/catch or if/else is enough:
// Prepare an insert statement
$sql = "INSERT INTO table(value) VALUES (:value)";
$stmt = $conn->prepare($sql);
// Bind variables to the prepared statement as parameters
$stmt->bindParam(':value', $value, PDO::PARAM_STR);
$stmt->execute(); //does each part here need an if/else?
You should only make the connection once. There's no need to close and reopen the connection between queries. I assume the reason the example at w3schools is written that way is so that it will be self-contained, executable as-is without relying on a connection established in another example.
If you have the code that defines your connection in one file like the first example you showed, you can include that file in other files that need a connection to execute queries, and $conn will be available there. For a simple project, that's all you really need.
As far as if/else or try/catch, since you have set the PDO::ATTR_ERRMODE attribute on your connection to PDO::ERRMODE_EXCEPTION, then wrapping bits of code where a query may fail in if/else probably won't be that useful, because an exception will be thrown if the query fails, so handling the exception in a catch block will work better. You can examine the exception to see exactly what went wrong, log the error, and show an appropriate error message to the user where applicable. Dumping every exception message to the screen as shown in the second example is generally not a good way to show appropriate error messages to users.
You should include the prepare, bind, and execute in the try block. execute() is not the only thing that can cause an exception. prepare() may throw an exception if you aren't using emulated prepared statements (depending on the setting of PDO::ATTR_EMULATE_PREPARES), and bind can also cause an exception, for example if you mess up a named placeholder.
if/else is more useful for checking the results of queries that executed successfully (e.g. did this select statement return any records). The level of detail of error handling you need determines how many if/else, try/catch blocks you need.
How can I perform a SQLite3 exec at the same time in PHP?
I have this code (by example):
$bd = new SQLite3("database.db");
$bd->busyTimeout(5000);
$bd->exec("INSERT into 'foo' ('data') values ('bar')");
$bd->close();
unset($bd);
And it works, but the real problem is when I connect another computer to my server and I made the insert at the same time (really, I press the key that trigger the code at the same time in both computers) and it show an error "database is locked".
I know that with the pragma WAL the database works in multithread, but it even show the error. Thank you a lot! and sorry for my bad english.
The problem is sqlite3 employs database locking, as opposed to row or column locking like mysql or postgresql. If you want to do two things at the same time try using mysql, or postgresql. In mysql you would have to create the database. Your code would then look something like this:
$servername = "localhost";
$username = "username";
$password = "password";
try {
$conn = new PDO("mysql:host=$servername;dbname=myDB", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
$count = $conn->exec("INSERT into 'foo' ('data') values ('bar')");
$conn = null // close connection
I want to select a MySQL database to use after a PHP PDO object has already been created. How do I do this?
// create PDO object and connect to MySQL
$dbh = new PDO( 'mysql:host=localhost;', 'name', 'pass' );
// create a database named 'database_name'
// select the database we just created ( this does not work )
$dbh->select_db( 'database_name' );
Is there a PDO equivalent to mysqli::select_db?
Perhaps I'm trying to use PDO improperly? Please help or explain.
EDIT
Should I not be using PDO to create new databases? I understand that the majority of benefits from using PDO are lost on a rarely used operation that does not insert data like CREATE DATABASE, but it seems strange to have to use a different connection to create the database, then create a PDO connection to make other calls.
Typically you would specify the database in the DSN when you connect. But if you're creating a new database, obviously you can't specify that database the DSN before you create it.
You can change your default database with the USE statement:
$dbh = new PDO("mysql:host=...;dbname=mysql", ...);
$dbh->query("create database newdatabase");
$dbh->query("use newdatabase");
Subsequent CREATE TABLE statements will be created in your newdatabase.
Re comment from #Mike:
When you switch databases like that it appears to force PDO to emulate prepared statements. Setting PDO::ATTR_EMULATE_PREPARES to false and then trying to use another database will fail.
I just did some tests and I don't see that happening. Changing the database only happens on the server, and it does not change anything about PDO's configuration in the client. Here's an example:
<?php
// connect to database
try {
$pdo = new PDO('mysql:host=huey;dbname=test', 'root', 'root');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $err) {
die($err->getMessage());
}
$stmt = $pdo->prepare("select * from foo WHERE i = :i");
$result = $stmt->execute(array("i"=>123));
print_r($stmt->fetchAll(PDO::FETCH_ASSOC));
$pdo->exec("use test2");
$stmt = $pdo->prepare("select * from foo2 WHERE i = :i AND i = :i");
$result = $stmt->execute(array("i"=>456));
print_r($stmt->fetchAll(PDO::FETCH_ASSOC));
If what you're saying is true, then this should work without error. PDO can use a given named parameter more than once only if PDO::ATTR_EMULATE_PREPARES is true. So if you're saying that this attribute is set to true as a side effect of changing databases, then it should work.
But it doesn't work -- it gets an error "Invalid parameter number" which indicates that non-emulated prepared statements remains in effect.
You should be setting the database when you create the PDO object. An example (from here)
<?php
$hostname = "localhost";
$username = "your_username";
$password = "your_password";
try {
$dbh = new PDO("mysql:host=$hostname;dbname=mysql", $username, $password);
echo "Connected to database"; // check for connection
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
Alternatively, you can select a MySQL database to use after a PHP PDO object has already been created as below:
With USE STATEMENT. But remember here USE STATEMENT is mysql command
try
{
$conn = new PDO("mysql:host=$servername;", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->exec("use databasename");
//application logic
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
I hope my code is helpful for requested
As far as I know, you have to create a new object for each connection. You can always extend the PDO class with a method which connects to multiple databases. And then use it as you like:
public function pickDatabase($db) {
if($db == 'main') {
return $this->db['main']; //instance of PDO object
else
return $this->db['secondary']; //another instance of PDO object
}
and use it like $yourclass->pickDatabase('main')->fetchAll('your stuff');
I want to wean myself from the teat of the old mysql extension and am just doing a test PDO connection and simple query on a table in a database. I seem to be able to connect, ('connection successful' echoes out) but that's where the good times end. I have spent way too much time now just trying to get started with PDO.
<?php
$host = 'localhost';
$port = '3306';
$username = 'user';
$password = 'blabla';
$database = 'workslist';
try {
$db = new PDO("mysql:host=$host; port = $port; dbname = $database", $username, $password);
echo 'connection successful<br />';
$query = 'SELECT * FROM main';
$statement = $db->prepare($query);
$statement->execute();
$results = $statement->fetchAll();
$statement->closeCursor();
foreach($results as $r){
echo $r['work'] . '<br />';
}
} catch (PDOException $e) {
echo 'Error!: ' . $e->getMessage() . '<br />';
die();
}
?>
Is there anything wrong with the above?
The database name is 'workslist', the table name is 'main', and 'work' is one of the columns in that table. The PHP version I'm using is 5.3.4, and am using wamp on win7. I ran phpinfo() and under the PDO heading, the PDO drivers mysql, sqlite are enabled. To be sure the database and table actually exist I've tried it with MySQL and can return rows with the old mysql_fetch_array() method. I've checked the php.ini file to make sure the "extension=php_pdo..." lines are all uncommented.
cheers
This should work.
Please double-check that you actually have a table named "main" in that database.
Note that this error will not be discovered by PDO until you execute() the query, and if there is a problem with your query the default behavior is to return an empty result, not throw an exception.
To make PDO noisier, add the PDO::ERRMODE_EXCEPTION option when constructing PDO:
$db = new PDO("mysql:host=$host;port=$port;dbname=$database", $username, $password,
array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION)
);
Now check if you see the following:
Error!: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'workslist.main' doesn't exist
The particular problem is that spaces aren't allowed in the DSN string. With the spaces, the "dbname" directive isn't processed, so there's no default database. Besides removing the spaces, explicitly specifying the database in the statement can help prevent this sort of problem:
SELECT `work` FROM `workslist`.`main`
That way, should there not be a default database for some reason, the query will still succeed.
PDO won't throw an error unless you configure it to:
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
The server is running PHP 5.2.8. PDO has mysql 5.1.30 drivers installed.
Alright, so I am trying to figure out some PDO ( and this is just killing me. When I run the code below, I get the expected results, no problem.
However, whenever I try to add more than one column (or *) to the SELECT, there is no reply from the query - no results whatsoever. I have tried everything - I know it must be something simple. Any suggestions as to why more than one column fails to return any rows?
$hostname = "localhost";
$dbname = "dbname";
$username = "username";
$password = "password";
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';
/*** The SQL SELECT statement ***/
$sql = "SELECT LastName FROM staff";
foreach ($dbh->query($sql) as $row) {
echo $row['LastName'] . '<br />';
}
/*** close the database connection ***/
$dbh = null;
} catch(PDOException $e) {
echo $e->getMessage();
}
Again, if I try to add columns in the statement stored in $sql to anything other than a single column, I get bupkis. For example:
SELECT FirstName, LastName FROM staff
returns zero results. Both columns exist - if requested separately, they return expected results. When combined, the query takes quite some time, then returns nothing.
No exception is caught by the catch block.
I think you have a number of issues here, mostly in your code that handles reading the values returned by the query. I have taken the liberty of changing a few things and rewriting this to use prepare statements, which is a function that PDO provides that you should take advantage of.
On prepare statements:
Why use them: http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html
PHP PDO doc: http://php.net/manual/en/pdo.prepare.php
Here is the core code:
try {
//open database
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
//define sql query
$sql = "SELECT LastName FROM staff";
//prepare the query for execution
$qresult = $dbh->prepare($sql);
//insert code below to handle parameters to the sql query here
//execute the query
$qresult->execute();
//fetch the results
foreach ($qresult->fetch(PDO::FETCH_ASSOC) as $row)
{
echo $row['LastName'] . '<br />';
}
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
$qresult = null; //close the result set
$dbh = null; //close the database
Note, that I have replaced the call to query() with a couple of lines that call prepare() then execute(). You can then easily insert the following lines in between the prepare() and execute() calls to handle passing parameterized queries. This will help reduce chances of sql injection.
I have also changed the way you are accessing the retirned valued by specifying that I want them returned as and associative array, PDO::FETCH_ASSOC. This will get you a result set that you can iterate through like you would have using the old mysql interfaces.
If your query was a parameterized query like:
$sql="SELECT LastName FROM staff WHERE LastName=':lastname'";
where :lastname is the parameter.
Here is the code you would insert at the comment to handle this, (this code will handle multiple parameters. Simply add additional elements to the $param array):
//bind parameters to the prepared statement
$param = array(':lastname'=>'Jones');
foreach ($param as $key => $value) {
$qresult->bindValue($key,$value);
}
Make sure you separate the columns in the SELECT with a comma (space on either side of the comma is okay, but not required). If you want to select all columns, have only a * with no other characters.