使用Doctrine 2执行原始SQL


102

我想使用Doctrine 2执行原始SQL

我需要截断数据库表并使用默认测试数据初始化表。


2
顺便说一句,当我想执行自动化数据库任务时,例如执行mysqldumps或从以前的转储或删除表中加载数据时,通常会为该工作编写一个shell脚本,然后以Symfony2语言编写一个任务(或“命令”) )执行shell脚本。据我所知,ORM的目的是抽象出重复的工作,如果您要进行诸如截断表格之类的工作,我不认为将Doctrine引入画面是有道理的,因为Doctrine并没有这样做。不会使这项任务变得更容易。
詹森·斯威特

Answers:


164

这是我正在做的Doctrine 2中的原始查询的示例:

public function getAuthoritativeSportsRecords()
{   
    $sql = " 
        SELECT name,
               event_type,
               sport_type,
               level
          FROM vnn_sport
    ";

    $em = $this->getDoctrine()->getManager();
    $stmt = $em->getConnection()->prepare($sql);
    $stmt->execute();
    return $stmt->fetchAll();
}   

4
好答案。要获得此代码中的实体管理器,您可以使用$ this-> getDoctrine()-> getManager()代替“ $ this-> getEntityManager()”上方的此代码,这样就可以立即为我工作。
webblover 2014年

嘿,这给了我调用未定义方法Index :: getDoctrine()我该怎么办
Dexter

即时通讯与教义2 一起
Dexter

1
这将我引向正确的方向,但并非我真正需要的。我怀疑答案的年龄会有所不同。我曾经用过:...getConnection()->query($sql);而且不必跑步$stmt->execute();
Brandon

请注意,使用Symfony4和自动装配,您可以键入提示EntityManagerInterface $entityManager,然后致电$entityManager->getConnection()
COil

50
//$sql - sql statement
//$em - entity manager

$em->getConnection()->exec( $sql );

18
调用prepare()而不是exec也是一个好主意,因此您仍然可以获得准备好的语句支持。
杰里米·希克斯

44

假设您正在使用PDO,我可以通过执行此操作来使其工作。

//Place query here, let's say you want all the users that have blue as their favorite color
$sql = "SELECT name FROM user WHERE favorite_color = :color";

//set parameters 
//you may set as many parameters as you have on your query
$params['color'] = blue;


//create the prepared statement, by getting the doctrine connection
$stmt = $this->entityManager->getConnection()->prepare($sql);
$stmt->execute($params);
//I used FETCH_COLUMN because I only needed one Column.
return $stmt->fetchAll(PDO::FETCH_COLUMN);

您可以更改FETCH_TYPE以适合您的需求。


1
其中最好的例子
David

14

如何执行原始查询并返回数据。

挂上您的经理并建立新连接:

$manager = $this->getDoctrine()->getManager();
$conn = $manager->getConnection();

创建查询和fetchAll:

$result= $conn->query('select foobar from mytable')->fetchAll();

像这样从结果中获取数据:

$this->appendStringToFile("first row foobar is: " . $result[0]['foobar']);

1
query()用于当SQL返回您要使用的某些数据时;exec()适用于何时不使用
Jeffiekins

12

我发现答案可能是:

NativeQuery使您可以执行本机SQL,并根据您的规范映射结果。这种描述如何将SQL结果集映射到Doctrine结果的规范由ResultSetMapping表示。

来源:Native SQL


17
这是公认的答案,但是我仍然看不到Doctrine的这一部分有什么用,因为您始终需要ResultSetMapping。我不希望它将结果映射到Entities ....这默认情况下会运行任意SQL!
MikeMurko

2
@MikeMurko我发现这篇文章有助于在《教义2》中运行原始查询:forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett

同样,非本机 Native SQL不会执行所有可能的SQL查询。DELETE / UPDATE / INSERT将不起作用,某些表定义也不会遵循原则假设。(没有ID的M2M联接表)。因此,这个答案并不普遍。也不应接受,因为INSERT无法正常工作。
przemo_li 2015年


5

在您的模型中,创建原始SQL语句(以下示例是我必须使用但替代您自己的日期间隔的示例。如果执行SELECT,请在execute()调用中添加-> fetchall()。

   $sql = "DELETE FROM tmp 
            WHERE lastedit + INTERVAL '5 minute' < NOW() ";

    $stmt = $this->getServiceLocator()
                 ->get('Doctrine\ORM\EntityManager')
                 ->getConnection()
                 ->prepare($sql);

    $stmt->execute();

4

您不能,Doctrine 2不允许原始查询。似乎可以,但是如果尝试以下操作:

$sql = "SELECT DATE_FORMAT(whatever.createdAt, '%Y-%m-%d') FORM whatever...";
$em = $this->getDoctrine()->getManager();
$em->getConnection()->exec($sql);

主义将吐出一个错误,说DATE_FORMAT是一个未知函数。

但是我的数据库(mysql)确实知道该功能,所以基本上说来,Doctrine正在幕后(和背后)解析该查询,并找到一个它不理解的表达式,认为该查询无效。

因此,如果像我一样,您只想简单地将一个字符串发送到数据库并让它处理它(并让开发人员对安全性负全部责任),就算了吧。

当然,您可以对扩展进行编码,以某种方式允许这种扩展,但是您同样可以使用mysqli进行扩展,而将Doctrine保留为ORM事务。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.