Таблица обновления JOOQ с условием объединенной таблицы - PullRequest
1 голос
/ 04 ноября 2019

У меня есть две такие таблицы: Enrollment и Student

create table [LECTURE_DB].[dbo].[ENROLLMENT](
[EXAM_PASSED] bit null default ((0)),
[EXAM_TAKEN] bit null default ((0)),
[YEAR] int not null,
[LECTURE_ID] numeric(19) not null,
[STUDENT_ID] numeric(19) not null,
constraint [PK__ENROLLME__FE468F5B2739D489]
  primary key (
    [YEAR], 
    [LECTURE_ID], 
    [STUDENT_ID]
  )
)  

create table [LECTURE_DB].[dbo].[STUDENT](
[ID] numeric(19) identity(1, 1) not null,
[FIRSTNAME] varchar(255) null,
[GENDER] varchar(255) null,
[LASTNAME] varchar(255) null,
[YEAR_OF_BIRTH] int null,
constraint [PK__STUDENT__3214EC273493CFA7]
  primary key ([ID])
)

Я сейчас пытаюсь обновить группу Enrollments (столбец exam_passed) с некоторыми lastname s, Lecture_ID иyear. С этого у меня появилась идея использовать объединенную таблицу.

private void updateStudentExamPassed(boolean passed, int lidx, int year, String... studentName) {
    Enrollment enrollment = Enrollment.ENROLLMENT;
    Student student = Student.STUDENT;

    Table<?> joined = enrollment.leftJoin(student).on(enrollment.STUDENT_ID.eq(student.ID));
    ctx.update(joined)        
        .set(enrollment.EXAM_PASSED, passed)
        .where(student.LASTNAME.in(studentName))
        .and(enrollment.YEAR.eq(year))
        .and(enrollment.LECTURE_ID.eq(BigInteger.valueOf(lidx)))
        .execute();       
    }

Но я получаю DataAccessException на .execute()

Exception in thread "main" org.jooq.exception.DataAccessException: SQL [update [LECTURE_DB].[dbo].[ENROLLMENT] left outer join [LECTURE_DB].[dbo].[STUDENT] on [LECTURE_DB].[dbo].[ENROLLMENT].[STUDENT_ID] = [LECTURE_DB].[dbo].[STUDENT].[ID] set [LECTURE_DB].[dbo].[ENROLLMENT].[EXAM_PASSED] = ? where ([LECTURE_DB].[dbo].[STUDENT].[LASTNAME] in (?, ?) and [LECTURE_DB].[dbo].[ENROLLMENT].[YEAR] = ? and [LECTURE_DB].[dbo].[ENROLLMENT].[LECTURE_ID] = ?)]; Falsche Syntax in der Nähe des left-Schlüsselworts.
at org.jooq_3.12.1.SQLSERVER2014.debug(Unknown Source)
at org.jooq.impl.Tools.translate(Tools.java:2717)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:755)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:383)
at org.jooq.impl.AbstractDelegatingQuery.execute(AbstractDelegatingQuery.java:119)
at de.esteam.lecturedb.jooq.tasks.RecordFeaturesTask.updateStudentExamPassed(RecordFeaturesTask.java:42)
at de.esteam.lecturedb.jooq.tasks.RecordFeaturesTask.run(RecordFeaturesTask.java:28)
at de.esteam.lecturedb.jooq.common.LectureDBAnalysis.run(LectureDBAnalysis.java:100)
at de.esteam.lecturedb.jooq.common.LectureDBAnalysis.main(LectureDBAnalysis.java:56)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Falsche Syntax in der Nähe des left-Schlüsselworts.

Документация мне не помогла, так как условие основано на другой таблице. Есть ли надежда, чтобы это сработало, или мне нужно, чтобы каждая Регистрация была самостоятельной и обновлялась в одиночку?

1 Ответ

2 голосов
/ 04 ноября 2019

Использование специального синтаксиса поставщика

Вопрос, который вы связали , касается MySQL. SQL Server не поддерживает этот вид синтаксиса, но вы можете получить эквивалентную семантику, используя предложение UPDATE .. FROM. Т.е. попробуйте это:

ctx.update(enrollment)        
    .set(enrollment.EXAM_PASSED, passed)
    .from(joined)
    .where(student.LASTNAME.in(studentName))
    .and(enrollment.YEAR.eq(year))
    .and(enrollment.LECTURE_ID.eq(BigInteger.valueOf(lidx)))
    .execute();

Обратите внимание, что LEFT JOIN здесь не имеет никакого смысла, если вы снова превращаете его в INNER JOIN, имея предикат на таблице student в вашем WHERE предложение.

Использование стандартного синтаксиса

Я лично предпочитаю использовать стандартный синтаксис SQL, когда это возможно в этих случаях, поскольку эти операторы UPDATE .. FROM или UPDATE .. JOIN часто можно заменить на IN или EXISTS предикаты. Например:

ctx.update(enrollment)        
    .set(enrollment.EXAM_PASSED, passed)
    .where(enrollment.STUDENT_ID.in(
        select(student.ID)
        .from(student)
        .and(student.LASTNAME.in(studentName))
    ))
    .and(enrollment.YEAR.eq(year))
    .and(enrollment.LECTURE_ID.eq(BigInteger.valueOf(lidx)))
    .execute();
...