I just want to delete the row with the lowest ID.
I'm trying this:
$query = 'DELETE FROM PATH\TO\ENTITY ORDER BY id ASC LIMIT 1';
$query = $this->entityManager->createQuery($query);
$query->execute();
And getting this error:
[Syntax Error] line 0, col 53: Error: Expected end of string, got 'BY'
Maybe I'm using the wrong approach.
Any suggestions how to delete the entry with the lowest id in one database call?
As Kwido said, you miss the entity alias. But the query will still not be able to execute.
First, DQL does not support LIMIT expression. It is MySQL-specific feature, is not an ANSI SQL. Other platform drivers have an own implementations of this behavior, all of them provided by common interface: setFirstResult()/setMaxResult() of Query object.
Second, DQL does not support DELETE with ORDER BY clause (see language EBNF). It is non-standard feature too, but can not be implemented for other drivers, so Doctrine does not allow it.
If you need to execute this query, you will have to use a native SQL.
Define an alias for your entity as you use DQL. See: Doctrine - By DQL
$query = $this->entityManager->createQuery('SELECT e FROM MyEntity e ORDER BY e.id ASC');
$query->setMaxResults(1); // LIMITS 1
$entities = $query->getResult();
if (count($entities) > 0) {
$query = $this->entityManager->createQuery('DELETE FROM MyEntity e WHERE e.id = :identifier');
$query->setParameter("identifier", $entities[0]->getId());
$query->execute();
}
Replace entityAlias with the first letter of your entity classname, which is the most common practice with Doctrine.
// Edit - as #Timurib stated DQL doesn't know the LIMIT. Should've used setMaxResults.
// Edit2 - As ORDER BY is not supported by the DELETE statement, but only the WHERE clause. We're now using another query to return the identifier before deleting. See DQL - Statements
$query = 'DELETE FROM table ORDER BY id ASC LIMIT 1';
$stmt = $this->entityManager->getConnection()->prepare($query);
$stmt->execute();
You cannot delete or update from entityManager. First you have to select/find the entity from Repository and then remove it. My suggestion works for raw SQL query instead.
Related
I am finding inputted user_id in accepted_join_id above query gives error as
syntax error, unexpected '$user_id' (T_VARIABLE)
$query=DB::select('select activity_id,accepted_join_id from table_user_create_activity WHERE FIND_IN_SET('$user_id',?) and activity_id=?',[$user_id,$accepted_join_id]);
if you want to inject $user_id value from php into your query try this:
$query=DB::select('select activity_id,accepted_join_id from table_user_create_activity WHERE FIND_IN_SET('.$user_id.',?) and activity_id=?',[$user_id,$accepted_join_id]);
or if $user_id is in query it should be like:
$query=DB::select('select activity_id,accepted_join_id from table_user_create_activity WHERE FIND_IN_SET("$user_id",?) and activity_id=?',[$user_id,$accepted_join_id]);
Getting following error
SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders
My query has become due to data in the table recently
SELECT
*
FROM
table
WHERE col1 = 'some-val'
AND col2 NOT IN ('va1', 'val2', 80k values... )
I am using Laravel 5.6
$data_will_be_skipped = OtherModel::select('code')
->where('col1', 0)
->orWhere('col2', 1)
->groupBy('col3')
->pluck('col3')->toArray();
$data_will_be_skipped is now approx 80k arrays
Model::where('col1', 'some-val')->whereNotIn('col2', $data_will_be_skipped)->get();
MySQL has a limit of 65,535 parameters in prepared statements.
Use a subquery instead:
$data_will_be_skipped = OtherModel::select('col3')
->where('col1', 0)
->orWhere('col2', 1);
Model::where('col1', 'some-val')
->whereNotIn('col2', $data_will_be_skipped)
->get();
No matter how many items u have in array to check in wherein
the simple way to do it
$data = model::whereRaw("id not in (".implode(',',$data_will_be_skipped).")")->get();
I would like to use a subquery inside a join, however Symfony2 throws the following error:
Here is my failed attempt:
$query = $em->createQuery(
'SELECT
sc.id AS id,
u.id AS userId,
u.username AS username,
sc_count.upvotes
FROM
myBundle:SuggestedCar sc
INNER JOIN myBundle:User u WITH sc.user_id = u.id
INNER JOIN ( SELECT sc1.user_id, COUNT(sc1.id) AS upvotes
FROM myBundle:SuggestedCar sc1
GROUP BY sc1.user_id
) sc_count WITH u.id = sc_count.user_id'
);
Basically I'm just joining 3 tables and the third one has a count. The query worked when executing it inside the database.
How would it be possible to use a SELECT statement inside a join? Is it a good idea to use raw SQL at this point?
The $em->createQuery() function is expecting DQL as the parameter, not SQL. If you want to execute a raw SQL statement, the syntax is different. You can do it like this:
$sql = "SELECT * FROM my_table";
$em = $this->getDoctrine()->getManager();
$stmt = $em->getConnection()->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll();
for more on DQL or querying for objects, see Querying for Object. The biggest difference is DQL will return an object (based on your entity classes in Symfony). The method I posted above will just give you a PDO result. So if you execute raw SQL, don't expect to be able to use the result as an object.
If you want to use raw SQL and still have the result mapped to an object, you can look at the doctrine docs about Result set mapping. In my opinion, this is more work than necessary.
Is there any mysql syntax to stop the query from being append by user input? If the query is
SELECT *
FROM `username`
WHERE `type` = 'client'
END / LIMIT / whatever syntax here;
the query should stop at 'client' so if user try to add his own query by adding OR such as this:
SELECT *
FROM `username`
WHERE `type` = 'client'
OR 1 = 1;
it will not work. Thanks in advance.
I will assume that you are using PHP and that 'client' is received as a parameter via $_POST from the user. In this scenario I think that what you want to do is prevent is SQL injection. If so you should solve it by using mysql_real_escape_string() to sanitize your input parameters:
// This could be supplied by a user, for example
$type = $POST['type'];
// Formulate Query
// This is the best way to perform an SQL query
// For more examples, see mysql_real_escape_string()
$query = sprintf("SELECT * FROM username
WHERE type='%s',
mysql_real_escape_string($type));
// Perform Query
$result = mysql_query($query);
...
I took this sample from the mysql-query reference and adapted it for your needs.
List<Lahetys> last = session.createQuery("from lahetys order by lahetysNro DESC LIMIT 1").list();
and in the log I got:
INFO: Hibernate: select from order by lahetysNro DESC LIMIT 1
WARN: SQL Error: 1064, SQLState: 42000
ERROR: 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 order by lahetysNro DESC LIMIT 1' at line 1
What has happend to "from LAHETYS"? What is the best practice to handle that with HQL or/and with SQL?
Another problem:
Lahetys last = (Lahetys)session.createSQLQuery("select * from lahetys order by lahetysNro DESC LIMIT 1").uniqueResult();
session.getTransaction().commit();
and I get a exception:
Ljava.lang.Object; cannot be cast to Lahetys
So I can't cast an object to my Lahetys-object, weird?
Thank you!
Sami
Your HQL query is invalid. LIMIT is not a valid HQL clause. To do that in Hibernate, just do
Query query = session.createQuery("from lahetys order by lahetysNro DESC");
query.setMaxResults(1);
Lahetys last = (Lahetys) query.uniqueResult();
When you're using HQL, you should specify fully qualified className instead of tableName. The same way you should specify propertyName instead of columnName. Also keep in mind that both are case - sensitive.
Looking at your queries & the exception you're getting, I'm assuming that lahetys is your table name & lahetysNro is your column name.
You should use for example: If your Lahetys class is located at com folder:
List<Lahetys> last = session.createQuery("from com.Lahetys order by lahetysNro DESC LIMIT 1").list();
For your 2nd question:
Here you have used SQL instead of HQL.
When you use SQL with hibernate in such a way, it always returns List<Object[]> & not List<Lahetys[]>.