您的位置:首页 > 数据库 > SQL

django中sql语句的查询

2015-10-28 13:22 501 查看
执行原始SQL查询

当 模型查询api 不要走得足够远,你 可以回到写原始SQL。 Django提供了两种方式执行原始 SQL查询:您可以使用 Manager.raw() 来 执行原始查询和 回归模型实例 ,或者你可以完全避免模型层 执行自定义SQL直接 。

执行原始查询

的 生() 经理的方法可以用来执行原始的SQL查询 回归模型实例:

经理。 生 ( raw_query , params =没有 , 翻译=没有 )

这个方法方法接受一个原始SQL查询,执行它,并返回一个 django.db.models.query.RawQuerySet 实例。 这 RawQuerySet 实例 可以遍历就像正常QuerySet提供对象实例。

这是最好的说明了一个例子。 假设你有以下模型:

class Person(models.Model):
first_name = models.CharField(...)
last_name = models.CharField(...)
birth_date = models.DateField(...)


然后您可以执行自定义SQL

>>>for p in Person.objects.raw('SELECT * FROM myapp_person'):
print(p)
>>>John Smith
>>>Jane Jones


这个例子不是非常令人兴奋的——它是一模一样 运行 Person.objects.all() 。 然而, 生() 有一些其他的吗 选项,使它非常强大。

模型表名

的名字哪里来的 人 表来自例子吗?

默认情况下,Django找出通过加入一个数据库表名称 模型的“应用程序”标签中使用的名称 jobs startapp - 模型的类名,它们之间用下划线。 在这个例子中 我们假定 人 生活在一个应用程序命名模式 myapp , 所以它的表 myapp_person 。

详情查看的文档 db_table 选项,也可以手动设置 数据库表的名称。

警告

没有完成检查传递给SQL语句 .raw() 。 Django预计的语句会返回一组行 数据库,但是并没有执行。 如果查询没有 返回行,(可能的)错误的结果。

查询字段映射到领域模型

生() 自动查询中的字段映射到领域模型。

查询字段的顺序并不重要。 换句话说,两个 下面的查询工作相同:

>>> Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person')

>>> Person.objects.raw('SELECT last_name, birth_date, first_name, id FROM myapp_person')


通过名字来匹配。 这意味着您可以使用SQL 作为 条款 查询中的字段映射到领域模型。 如果你有一些其他的表 有 人 数据,您可以轻松地将它映射 人 实例:

>>> Person.objects.raw('''SELECT first AS first_name,
last AS last_name,
bd AS birth_date,
pk as id,
FROM some_other_table''')


只要名字匹配,将正确创建模型实例。

或者,您可以查询中的字段映射到模型领域使用 翻译 参数 生() 。 这是一个字典映射的名字 查询中的字段名称的领域模型。 例如,上面的 查询也可以写成:

>>> name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
>>> Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)


索引查找

生() 支持索引,因此,如果您只需要第一个结果 写:

>>> first_person = Person.objects.raw('SELECT * from myapp_person')[0]


然而,索引和切片并不在数据库级别上执行。 如果 你有一个大的 人 数据库中的对象,它是更多 有效限制查询在SQL级:

>>> first_person = Person.objects.raw('SELECT * from myapp_person LIMIT 1')[0]


延迟模型领域

字段可能也被排除在外:

>>> people = Person.objects.raw('SELECT id, first_name FROM myapp_person')


的 人 这个查询返回的对象将被延迟模型实例 (见 推迟() )。 这意味着 字段省略从查询将被加载到需求。 例如:

>>> for p in Person.objects.raw('SELECT id, first_name FROM myapp_person'):
print(p.first_name, # This will be retrieved by the original query
p.last_name) # This will be retrieved on demand

John Smith
Jane Jones


从外表,这看起来像查询检索 第一名和姓。 然而,这个例子其实发行3 查询。 只有第一个名字被生()检索查询的 姓都检索时印刷的需求。

只有一个领域,你不能离开——主键 字段。 Django使用主键来确定模型实例,所以它 必须始终包含在原始查询。 一个 InvalidQuery 异常 将提高如果你忘了包括主键。

添加注释

您还可以执行查询定义不包含字段 模型。 例如,我们可以使用 PostgreSQL的年龄()函数 得到一个列表 的人与他们的年龄计算的数据库:

>>> people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person')
>>> for p in people:
print("%s is %s." % (p.first_name, p.age))
John is 37.
Jane is 42.


传递参数到 生()

如果你需要进行参数化查询,您可以使用 参数个数 参数 生() :

>>> lname = 'Doe'
>>> Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])


参数个数 的参数是一个列表或字典。 您将使用 % s 在查询字符串中占位符的列表,或 %(关键) (占位符一本词典 关键 取而代之的是一个 当然,字典键),不管你的数据库引擎。 这样的 占位符将被替换的参数 参数个数 论点。

请注意

字典参数不支持使用SQLite

字典参数不支持SQLite的后端; 这个后台,你必须通过参数作为一个列表。

警告

不要使用在原始查询字符串格式化!

人们很容易把上面的查询写成:

>>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
>>> Person.objects.raw(query)


不喜欢。

使用 参数个数 论点完全保护你 SQL注入 攻击 ,一个攻击者任意SQL注入的共同开发 您的数据库。 如果你使用字符串插值,迟早你会 SQL注入的受害者。 只要你记得总是使用 参数个数 论证你会保护。

改变了Django 1.6:

在Django 1.5和更早的,你可以通过参数作为字典 当使用PostgreSQL或MySQL,尽管这不是记录。 现在 您还可以使用Oracle这样做的时候,这是官方支持。

直接执行自定义的SQL

有时甚至 Manager.raw() 没有足够的:你可能需要 执行查询,不简洁地映射到模型,或直接执行 更新 , 插入 ,或 删除 查询。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: