我最近不得不检修一个最初使用MySQL的Django项目,但是为了部署到Heroku(按照他们在Django部署文档中的建议),我通过以下方法将MySQL数据库迁移到Postgres:
安装的依赖项:pyscopg2和py-mysql2pgsql
设置Postgres数据库
迁移的数据库:$ py-mysql2pgsql—这将创建一个mysql2pgsql.yml文件,如下所示:
mysql:
hostname: localhost
port: 3306
socket: /tmp/mysql.sock
username: foo
password: bar
database: your_database_name
compress: false
destination:
postgres:
hostname: localhost
port: 5432
username: foo
password: bar
database: your_database_name
通过以下方式传输数据:$ py-mysql2pgsql -v -f mysql2pgsql.yml
喝了几杯咖啡之后,成功部署到了Heroku(在很大程度上,直到今天我发现了这个问题),并且该应用程序在heroku和我运行时按预期工作$ heroku local。但是今天,当访问前端的某个函数时,浏览器中出现了数据库错误:
DatabaseError at /projects/
syntax error at or near "SEPARATOR"
LINE 1: ...s, sc.name as sport_category, string_agg(au.email SEPARATOR ...
^
Request Method: GET
Request URL: http://0.0.0.0:8989/projects/
Django Version: 1.5.1
Exception Type: DatabaseError
Exception Value:
syntax error at or near "SEPARATOR"
LINE 1: ...s, sc.name as sport_category, string_agg(au.email SEPARATOR ...
我相信相关代码位于名为business.py的文件中:
def getAllProjects(self):
'''
@note: Retrieve all projects
'''
from django.db import connection
cursor = connection.cursor()
cursor.execute("select p.id, p.title, p.description, p.deadline, pt.name as project_type, s.name as status, sc.name as sport_category, group_concat(au.email SEPARATOR '\n') as project_managers from project p left join project_manager_in_project pmip on p.id = pmip.project_id left join auth_user au on pmip.project_manager_id = au.id inner join project_type pt on p.projectType_id = pt.id inner join status s on p.status_id = s.id inner join sport_category sc on p.sportCategory_id = sc.id where p.deleted = 0 group by p.id")
projects = cursor.fetchall()
return projects
我知道一些有关类似问题的文章:
这导致我尝试更改group_concat(au.email SEPARATOR '\n')为string_agg(au.email SEPARATOR '\n'),然后array_agg(au.email SEPARATOR '\n')仍然遇到相同的错误。
我还有其他方法可以解决此问题并调整此功能以实现解决方法吗?
更新:对于任何有兴趣的人,下面的“考虑我”提供的选定答案(和评论)使我进入以下更改的查询语句,该语句到目前为止没有问题:
cursor.execute("select \"project\".\"id\", project.title, project.description, \"project\".\"deadline\", \"pt\".\"name\" as \"project_type\", \"sc\".\"name\" as status, \"sc\".\"name\" as sport_category, string_agg(au.email, E'\n') as project_managers from project left join project_manager_in_project pmip on project.id = pmip.project_id left join auth_user au on pmip.project_manager_id = au.id inner join project_type pt on project.\"projectType_id\" = pt.id inner join status s on project.\"status_id\" = \"s\".id inner join sport_category sc on \"project\".\"sportCategory_id\" = \"sc\".\"id\" where project.deleted = 0 group by 1,2,3,4,5,6,7")
由于该应用程序的原始开发人员创建了所有带有双引号的表,因此导致column p.projecttype_id does not exist错误和其他类似的does not exist错误(在我所做的所有操作都删除SEPARATOR并更改group_concat为Postgres中都不存在)后不断出现string_agg。换句话说,按照“考虑我”的建议,我不得不用双引号将几乎所有的表名和列名封装起来(当然要避免使用引号)。
解决方案
如您所见,您需要替换GROUP_CONCAT()为STRING_AGG()。在GROUP BY子句中的聚合函数中包括所有未使用的列。
select
p.id,
p.title,
p.description,
p.deadline,
pt.name as project_type,
s.name as status,
sc.name as sport_category,
string_agg(au.email, E'\n') as project_managers
from
project p
left join project_manager_in_project pmip on p.id = pmip.project_id
left join auth_user au on pmip.project_manager_id = au.id
inner join project_type pt on p.projectType_id = pt.id
inner join status s on p.status_id = s.id
inner join sport_category sc on p.sportCategory_id = sc.id
where
p.deleted = 0
group by 1,2,3,4,5,6,7
SEPARATORPostgres中没有关键字(至少我不知道它的存在)。