How to do a native sql query in Doctrine 2, executing an update statement?
The createNativeQuery method on EntityManager, requires a second parameter (ResultSetMapping) to be able to map the resultsets to Objects.
But when updating (or inserting, or set, or...) there is no resulset to map.
Passing null or just new ResultSetMapping(), gives an error.
Are only select queries supported for native sql?
Essentially ditto w/ faken,
this from the docs:
If you want to execute DELETE, UPDATE or INSERT statements the Native
SQL API cannot be used and will probably throw errors. Use
EntityManager#getConnection() to access the native database connection
and call the executeUpdate() method for these queries.
one note of use is the connection object can be retrieved from the EntityManager:
$conn = $entityManager->getConnection();
$rowsAffected = $conn->executeUpdate($sql, $params, $types);
Update statements are usually pretty simple, so you might as well use the normal Doctrine2 way (i.e. programmatically updating entities and calling EntityManager::flush() OR using DQL Updates).
Having said this, if you really want to use normal SQL, you could always do it like this:
Keep the db connection object you get when creating a connection with Doctrine2:
$connection = \Doctrine\DBAL\DriverManager::getConnection($dbConfig->toArray(),null,$evm);
Execute whatever SQL you want, using the available methods in the connection object, e.g.:
$connection->executeUpdate($sql, $params, $types);
$connection->exec($sql);
...
Related
I'm using laravel with multiple DB connection. Oracle and PostgreSQL. I can do query from both of instance.
But the problem is I have to look inside my Oracle DB WHERE NOT EXISTS on my postgreSQL.
This is my current Query :
DB::connection('ora')->table('ora_purch')
->whereExists(function($query)
{
$query->select(DB::connection('pgs')->raw(1))
->from('pg_purch')
->whereRaw('ora_purch.id = pg_purch.id');
})
->get();
From this query, I get error "database pg_purch is not exists". It's just like laravel reads pg_purch as an oracle instance.
I also do simulation with the same query and the same instance (multiple database on postgreSQL only), the query is fine and produces correct data.
Is it possible to makes the laravel reads pg_purch refer to the connection?
Or maybe i've missing something?
Please advise, thank you.
Your code generates query like this:
SELECT * FROM ora_purch WHERE EXISTS (SELECT 1 FROM pg_purch WHERE ora_purch.id = pg_purch.id);
And make it with "ora" connection, ignoring "pgs" connection.
You can't use multiple connections inside one query.
Try to split them:
$ids = DB::connection('pgs')->from('pg_purch')->pluck('id');
$result = DB::connection('ora')->from('ora_purch')->whereIn('id', $ids)->get();
When using Eloquent outside of Laravel and using the Capsule\Manager class, I can't see how to create a SQL view, only a SQL table. When using Eloquent with Laravel, you can do something like:
DB::statement( "CREATE VIEW foo AS SELECT id, name FROM . . .
But the Capsule\Manager class doesn't have a statement() method or any way to execute raw SQL (like the statement() method does) that I can see.
The Capsule\Manager class seems to let you do everything else you can normally do with Eloquent, surely there's a way to create a view?
If you need to execute raw SQL you can use Manager::connection() to get the connection object which has statement and raw methods. Try this:
$db = \Illuminate\Database\Capsule\Manager::connection();
$db->statement($db->raw('CREATE VIEW `foo` AS SELECT * FROM `bar`'));
I am trying to add more error outputs to my code as it is growing. But I am not sure how deep I need to go. For instance, if I send a PDO DELETE FROM command to a table, is it necessary for me to then query the table again to see if the row was deleted (and confirm to the user)? Or should I rely on error handling, as in, if there was no error, it was definitely successful.
Thanks.
You should wrap every SQL statement in a try and catch block to see if any SQL exceptions or any other exceptions occured.
Depending on how you execute your PDO queries you have two options.
You can execute a statement directly with the PDO class using the exec() function. This function will return the number of affected rows for each query. However this function does not return the number of affected rows for an SELECT query.
So for delete queries you would use
$connection = new PDO($dsn, $username, $password);
$affectedRows = $connection->exec('DELETE from users WHERE id = 1);
This way affectedRows will probably be 1 or 0 if the user doesn't exist. If any other errors occur the catch part of the try-catch block will make sure to fetch these.
If you want to execute an SELECT query and find out if it was successful I would recommend doing this
$connection = new PDO($dsn, $username, $password);
$statement = $connection->prepare(SELECT * FROM users);
$statement->execute();
$returnedUsers = $statement->fetchAll();
As you can see, calling the method $connection->prepare() will return a statement which is an object of the PDOStatement class.
If you have parameters set in the prepare query you would want to set these through the bindParam() methods of the PDOStatement class.
Keep in mind that when it's neccesary to execute multiple similar queries in one go use an object of PDOStatement and then set different parameters using the bindParam() method.
I have been working on an e-commerce website in PHP Lithium framework, actually this one is upgraded from CakePHP, we have to use transaction operation on db in mysql. Just don't know how to do db transaction in PHP Lithium framework.
Since Lithium uses PDO, you can just get the PDO object and call the beginTransaction() method.
$foo = app\models\Foo::create();
$pdo = Connections::get('default')->connection;
$pdo->beginTransaction();
$foo->bar = 'Hello';
$foo->save();
$pdo->commit();
https://github.com/UnionOfRAD/lithium/issues/1004#issuecomment-23690165
http://www.php.net/manual/en/pdo.begintransaction.php
It doesn't seem like it is supported, unfortunately. See source of lithium/data/source/database/adapter/MySql.php.
An alternative may be to manually execute your queries.
Within your model, you can do:
static::connection->read($sql, $placeholders);
Where $sql is your raw SQL like:
$sql = 'SELECT * FROM users WHERE id = {:id}';
and $placeholders (optional) are your placeholders:
$placeholders = [
'id' => 5
];
Using that knowledge, you should be able to set up a transaction.
I would like to retrieve all the tables of my database as a list.
i tried to do a "Show databases" on a query but as i'm not using a class I defined (entity) in symfony it's not working.
And with DQL :
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery(
'show databases');
$result = $query->getResult();
This error :
[Syntax Error] line 0, col 0: Error: Expected SELECT, UPDATE or DELETE, got 'show'
Any idea to help me ?
As mentioned in a different answer, you can use Doctrine\DBAL for that:
/** #type \Doctrine\DBAL\Connection $connection */
$connection = ...;
/** #type \Doctrine\DBAL\Schema\MySqlSchemaManager $sm */
$sm = $connection->getSchemaManager();
And then just list the tables as Array:
var_dump( $sm->listDatabases() );
My 2 cents:
getContainer()->get('doctrine.dbal.default_connection')->getSchemaManager()->listTableNames()
This will give you an array of table names.
i have a couple cases where I need to use complex sql statements/functions that I just couldn't do in DQL. Luckily, Symfony2/doctrine provide a method to grab the current database connection and bypass doctrine entirely.
//get connection
$conn = $this->get('database_connection');
//run a query
$users= $conn->fetchAll('select * from users');
Be very careful when using this method, however. Since you are bypassing doctrine, you need to handle any security concerns like SQL injection yourself.
You can add Doctrine DBAL to your project and it will give you the tools you need. You can list databases, tables from a database, columns from a table etc etc
More in Doctrine DBAL documentation: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/schema-manager.html
Doctrine is a ORM, it is not intended to list all the databases. Beside that, usually for the current user you don't have the right to show all databases in the server, this can prove to be a big security breach.
Basicly, doctrine does not know how to interpret your query, you have to use a native query for this: Doctrine Native Query