Convertir un script MySQL en PostgreSQL resulta en "ERROR: schema no existe" error

Tengo esta consulta en MySQL que lista todos los cursos de Moodle que han sido accedidos en los últimos 2 años y el usuario (+ su papel de Moodle) que último lo accedió. Estoy tratando de convertirlo a PostgreSQL 9.3.22 para que pueda funcionar en otro Moodle LMS I administra. Sin embargo, la consulta falla con el error ERROR: schema "cat" does not exist.

Pregunta MySQL:

select cat.id 'category id',
    cat.name 'category',
    lsl.courseid,
    c.fullname 'course fullname',
    case when c.visible = '1'
      then 'yes'
      else 'no'
    end as "course visibility",
    from_unixtime(max(lsl.timecreated), '%H:%i %D %M %Y') 'lastaccessed',
    lsl.userid 'lastaccesseduserid',
    u.username 'last accessed by',
    case when r.shortname is null
        then 'user is not enrolled in this course'
        else r.shortname
    end 'role'
from prefix_logstore_standard_log lsl
    join prefix_course c on c.id = lsl.courseid
    join prefix_course_categories cat on cat.id = c.category
    join prefix_user u on u.id = lsl.userid
    left join prefix_role_assignments ra on ra.contextid = lsl.contextid -- left join in case the last accessed user wasn't enrolled in the course (i.e. admin staff).
    left join prefix_role r on r.id = ra.roleid
group by lsl.courseid
having max(lsl.timecreated) > unix_timestamp(date_sub(now(), interval 24 month))
order by lsl.courseid asc

Mi intento de conversión de PostgreSQL:

select cat.id 'category id',
    cat.name 'category',
    lsl.courseid,
    c.fullname 'course fullname',
    case when c.visible = '1'
      then 'yes'
      else 'no'
    end as "course visibility",
    to_char(to_timestamp(max(lsl.timecreated)), 'HH24:MI DD/MM/YYYY') "last accessed date",
    lsl.userid 'lastaccesseduserid',
    u.username 'last accessed by',
    case when r.shortname is null
        then 'user is not enrolled in this course'
        else r.shortname 
    end "role"
from prefix_logstore_standard_log lsl
    join prefix_course c on c.id = lsl.courseid
    join prefix_course_categories cat on cat.id = c.category
    join prefix_user u on u.id = lsl.userid
    left join prefix_role_assignments ra on ra.contextid = lsl.contextid -- left join in case the last accessed user wasn't enrolled in the course (i.e. admin staff).
    left join prefix_role r on r.id = ra.roleid
group by lsl.courseid
having max(lsl.timecreated) > extract(epoch from now()- interval '2 year')
order by lsl.courseid asc

He comprobado el esquema de la base de datos, y la tabla existe, pero no entiendo por qué este error ocurre en la tabla de prefix_course_categorías solamente. No conozco PostgreSQL muy bien, así que su asistencia es muy apreciada!

Pregunta hecha hace 3 años, 4 meses, 28 días - Por debugdynamo05ee


2 Respuestas:

  • El error que estás experimentando ("ERROR: schema 'cat' does not exist") en PostgreSQL se debe a que estás haciendo referencia a un esquema que no existe en tu consulta. En PostgreSQL, los esquemas son un nivel de organización adicional que no se manejan de la misma manera que en MySQL.

    Para corregir este error, simplemente elimina el prefijo del esquema "cat." en la tabla "prefixcoursecategories" en tu consulta. PostgreSQL asume que "cat" es un esquema en sí mismo al verlo con un punto, y al no encontrarlo, te arroja el error.

    Aquí te dejo la corrección en tu consulta en PostgreSQL:

    sql
    select cat.id as "category id",
        cat.name as "category",
        lsl.courseid,
        c.fullname as "course fullname",
        case when c.visible = '1'
          then 'yes'
          else 'no'
        end as "course visibility",
        to_char(to_timestamp(max(lsl.timecreated)), 'HH24:MI DD/MM/YYYY') as "last accessed date",
        lsl.userid as lastaccesseduserid,
        u.username as "last accessed by",
        case when r.shortname is null
            then 'user is not enrolled in this course'
            else r.shortname
        end as "role"
    from prefix_logstore_standard_log lsl
        join prefix_course c on c.id = lsl.courseid
        join prefix_course_categories cat on cat.id = c.category
        join prefix_user u on u.id = lsl.userid
        left join prefix_role_assignments ra on ra.contextid = lsl.contextid 
        left join prefix_role r on r.id = ra.roleid
    group by cat.id, cat.name, lsl.courseid, c.fullname, c.visible, lsl.userid, u.username, r.shortname
    having max(lsl.timecreated) > extract(epoch from now() - interval '2 year')
    order by lsl.courseid asc;
    

    Con esta corrección, deberías poder ejecutar tu consulta en PostgreSQL sin problemas. Recuerda ajustar cualquier otro detalle necesario en la conversión de MySQL a PostgreSQL, como las funciones de fecha y hora, el formato de las consultas, etc. Si necesitas más ayuda, no dudes en preguntar. ¡Espero que esta información te sea útil!

    Respondida el Dec 19, 2020 a las 04:30 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El error "ERROR: cat" se produce porque la consulta MySQL utiliza la función cat, que no existe en PostgreSQL. Para convertir correctamente la consulta a PostgreSQL, debes reemplazar la función cat con la función category.

    Aquí tienes la consulta PostgreSQL corregida:

    sql
    select category.id 'category id',
        category.name 'category',
        lsl.courseid,
        c.name 'course fullname',
        case when c.visible = '1'
          then 'yes'
          else 'no'
        end as "course visibility",
        to_char(to_timestamp(max(lsl.timecreated)), 'HH24:MI DD/MM/YYYY') "last accessed date",
        lsl.userid 'lastaccesseduserid',
        u.username 'last accessed by',
        case when r.name is null
            then 'user is not enrolled in this course'
            else r.name
        end "role"
    from _logstore_standard_log lsl
        join _course c on c.id = lsl.courseid
        join _course_category category on category.id = c.category
        join _user u on u.id = lsl.userid
        left join _role_assignments ra on ra.contextid = lsl.contextid -- left join in case the last accessed user wasn't enrolled in the course (i.e. admin staff).
        left join _role r on r.id = ra.roleid
    group by lsl.courseid
    having max(lsl.timecreated) > (now() - interval '2 year')
    order by lsl.courseid;
    

    Los cambios principales son:

    La función cat se ha remplazado por category. Se ha actualizado la función from_ unixtime a to_char(to_timestamp()) para PostgreSQL.

    • El nombre de la tabla `_course_categories` se ha actualizado a `_course_category` para PostgreSQL.

    Espero que esto ayude! Avísame si tienes alguna otra pregunta.

    Respondida el Dec 19, 2020 a las 04:35 - por Gemini

    Votos positivos: 0 | Votos negativos: 0