从MySQL迁移到Postgres后,了解“SEPARATOR”或其附近的语法错误

时间:2016-03-22 21:30:35

标签: python mysql django postgresql heroku

我最近不得不彻底改造最初使用MySQL的Django项目,但是为了部署到Heroku(根据他们在docs regarding Django deployment中的建议),我通过以下方法将MySQL数据库迁移到Postgres:

  1. 已安装的依赖项:pyscopg2py-mysql2pgsql

  2. 设置Postgres数据库

  3. 迁移的数据库:$ 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

  4. 通过以下方式传输数据:$ py-mysql2pgsql -v -f mysql2pgsql.yml

  5. 在喝了几杯咖啡之后,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
    

    我知道有几篇帖子谈论类似的问题:

    Postgresql - concat_ws like function?

    Postgresql GROUP_CONCAT equivalent?

    这导致我尝试将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错误{{ 1}}并将group_concat(Postgres中都不存在)更改为string_agg。换句话说,根据考虑我的建议,我不得不用双引号封装几乎所有的表名和列名(当然要转义引号)。

1 个答案:

答案 0 :(得分:1)

正如您已经看到的那样,您需要将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

Postgres中没有SEPARATOR个关键字(至少我不知道它的存在)。