带括号的Oracle SQL错误

时间:2017-06-23 13:00:35

标签: sql oracle

我在Oracle SQL Query下面一直给我一个错误。我错过了右括号错误。我试着寻找缺失的括号,但它们似乎都在记事本编辑器中正确关闭。

SELECT EMPLOYEES.EMPLOYEEID, EMPLOYEES.NAME FROM EMPLOYEES WHERE Employees.EmployeeID NOT IN 
(
SELECT Services.EmployeeID FROM Services where 

SERVICES.CHECKOUT <>3 AND SERVICES.CHECKOUT <> 5 AND SERVICES.CHECKOUT <>6
AND 
(
TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS' BETWEEN SERVICES.STARTDATE AND SERVICES.ENDDATE) or  
TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS' BETWEEN SERVICES.STARTDATE AND SERVICES.ENDDATE) or
SERVICES.STARTDATE BETWEEN TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') AND TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') or
SERVICES.ENDDATE BETWEEN TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') AND TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS')
)

union

SELECT EMPBREAKS.EMPID FROM EMPBREAKS WHERE
TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') BETWEEN EMPBREAKS.STARTB AND EMPBREAKS.ENDB or 
TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') BETWEEN EMPBREAKS.STARTB AND EMPBREAKS.ENDB or 
EMPBREAKS.STARTB BETWEEN TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') AND TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') or
EMPBREAKS.ENDB BETWEEN TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') AND TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') or
(EMPBREAKS.FLAGCYCLIC =1 AND EMPBREAKS.DAYWEEKINDEX = 4 AND TO_DATE(TO_CHAR(EMPBREAKS.STARTB,'HH24:MI:SS'),'HH24:MI:SS') BETWEEN TO_DATE('11:00:00', 'HH24:MI:SS') AND TO_DATE('12:00:00', 'HH24:MI:SS')) or
(EMPBREAKS.FLAGCYCLIC =1 AND EMPBREAKS.DAYWEEKINDEX = 4 AND TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS'),'HH24:MI:SS') BETWEEN TO_DATE('11:00:00', 'HH24:MI:SS') AND TO_DATE('12:00:00', 'HH24:MI:SS')) or
(EMPBREAKS.FLAGCYCLIC =1 AND EMPBREAKS.DAYWEEKINDEX = 4 AND TO_DATE('11:00:00', 'HH24:MI:SS') BETWEEN TO_DATE(TO_CHAR(EMPBREAKS.STARTB, 'HH24:MI:SS'),'HH24:MI:SS') AND TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS'),'HH24:MI:SS')) or
(EMPBREAKS.FLAGCYCLIC =1 AND EMPBREAKS.DAYWEEKINDEX = 4 AND TO_DATE('12:00:00', 'HH24:MI:SS') BETWEEN TO_DATE(TO_CHAR(EMPBREAKS.STARTB, 'HH24:MI:SS', 'HH24:MI:SS') AND TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS'),'HH24:MI:SS')))
union
SELECT EMPSICKVACATIONS.EMP_NO FROM EMPSICKVACATIONS  Where EMPSICKVACATIONS.VDATE = TO_DATE('19/06/2017 00:00:00', 'DD/MM/YYYY HH24:MI:SS') or (EMPSICKVACATIONS.CYCLICFLAG = 1 AND EMPSICKVACATIONS.WEEKDAYINDEX = 4))

3 个答案:

答案 0 :(得分:2)

虽然您还没有让我们知道此查询产生了什么样的错误,但Oracle通常不会将多个左括号放在一起,尤其是在不需要它们的情况下。此外,您反复使用相同的常量 - 最好将它们放在表表达式中,然后将其交叉连接到子查询,以避免多次重新键入它们。重新格式化查询以消除不必要的括号,使其更具可读性,并使用表表达式来消除我们得到的常量:

WITH QUERY_DATA AS (SELECT TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') AS DT11,
                           TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') AS DT12,
                           TO_DATE('11:00:00', 'HH24:MI:SS') AS HH11,
                           TO_DATE('12:00:00', 'HH24:MI:SS') AS HH12)
SELECT EMPLOYEES.EMPLOYEEID, EMPLOYEES.NAME
  FROM EMPLOYEES
  WHERE EMPLOYEES.EMPLOYEEID NOT IN
          (SELECT SERVICES.EMPLOYEEID
             FROM SERVICES
             CROSS JOIN QUERY_DATA q
             WHERE SERVICES.CHECKOUT <> 3 AND
                   SERVICES.CHECKOUT <> 5 AND
                   SERVICES.CHECKOUT <> 6 AND 
                  (q.DT11 BETWEEN SERVICES.STARTDATE
                              AND SERVICES.ENDDATE OR
                   q.DT12 BETWEEN SERVICES.STARTDATE
                              AND SERVICES.ENDDATE OR
                   SERVICES.STARTDATE BETWEEN q.DT11
                                          AND q.DT12 OR
                   SERVICES.ENDDATE BETWEEN q.DT11
                                        AND q.DT12)
           UNION
           SELECT EMPBREAKS.EMPID
             FROM EMPBREAKS
             CROSS JOIN QUERY_DATA
             WHERE q.DT11 BETWEEN EMPBREAKS.STARTB
                              AND EMPBREAKS.ENDB OR
                   q.DT12 BETWEEN EMPBREAKS.STARTB
                              AND EMPBREAKS.ENDB OR
                   EMPBREAKS.STARTB BETWEEN q.DT12
                                        AND q.DT11 OR
                   EMPBREAKS.ENDB BETWEEN q.DT12
                                      AND q.DT11 OR
                  (EMPBREAKS.FLAGCYCLIC = 1 AND
                   EMPBREAKS.DAYWEEKINDEX = 4 AND
                   TO_DATE(TO_CHAR(EMPBREAKS.STARTB,'HH24:MI:SS'),'HH24:MI:SS') BETWEEN q.HH11
                                                                                    AND q.HH12) OR
                  (EMPBREAKS.FLAGCYCLIC = 1 AND
                   EMPBREAKS.DAYWEEKINDEX = 4 AND
                   TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS'),'HH24:MI:SS') BETWEEN q.HH11
                                                                                  AND q.HH12) OR
                  (EMPBREAKS.FLAGCYCLIC = 1 AND
                   EMPBREAKS.DAYWEEKINDEX = 4 AND
                   q.HH11 BETWEEN TO_DATE(TO_CHAR(EMPBREAKS.STARTB, 'HH24:MI:SS'),'HH24:MI:SS')
                              AND TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS'),'HH24:MI:SS')) OR
                  (EMPBREAKS.FLAGCYCLIC = 1 AND
                   EMPBREAKS.DAYWEEKINDEX = 4 AND
                   q.HH12 BETWEEN TO_DATE(TO_CHAR(EMPBREAKS.STARTB, 'HH24:MI:SS', 'HH24:MI:SS')
                              AND TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS'),'HH24:MI:SS')))
           UNION
           SELECT EMPSICKVACATIONS.EMP_NO
             FROM EMPSICKVACATIONS
             Where EMPSICKVACATIONS.VDATE = TO_DATE('19/06/2017 00:00:00', 'DD/MM/YYYY HH24:MI:SS') OR
                   (EMPSICKVACATIONS.CYCLICFLAG = 1 AND
                    EMPSICKVACATIONS.WEEKDAYINDEX = 4))

稍微观察一下,您会注意到在UNION的第二个查询中,有几个表达式看起来像

               EMPBREAKS.STARTB BETWEEN q.DT12
                                    AND q.DT11 OR
               EMPBREAKS.ENDB BETWEEN q.DT12
                                  AND q.DT11 OR

这将是一个问题,因为第一个日期(QUERY_DATA.DT12)大于第二个日期(QUERY_DATA.DT11)。在BETWEEN表达式中,第一个值必须小于或等于第二个值,否则永远不会满足表达式。这些应该改写为

               EMPBREAKS.STARTB BETWEEN q.DT11
                                    AND q.DT12 OR
               EMPBREAKS.ENDB BETWEEN q.DT11
                                  AND q.DT12 OR

祝你好运。

答案 1 :(得分:1)

解决这些问题

  1. 使用SQL开发者客户端的Code beautifier / formatter功能,建议使用一个,因为有很多很酷的功能。
  2. 复制代码并点击快捷方式格式化代码
  3. 您的代码格式会中断,有问题或突出显示
  4. 可以调整代码格式,因为大多数编辑都具有该功能。
  5. SELECT EMPLOYEES.EMPLOYEEID, EMPLOYEES.NAME FROM EMPLOYEES WHERE Employees.EmployeeID NOT IN ( ( SELECT Services.EmployeeID FROM Services WHERE ( ( SERVICES.CHECKOUT <>3 AND SERVICES.CHECKOUT <> 5 AND SERVICES.CHECKOUT <>6 ) AND ( ( TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') BETWEEN SERVICES.STARTDATE AND SERVICES.ENDDATE ) OR ( TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') BETWEEN SERVICES.STARTDATE AND SERVICES.ENDDATE ) OR ( SERVICES.STARTDATE BETWEEN TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') AND TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') ) OR ( SERVICES.ENDDATE BETWEEN TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') AND TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') ) ) ) ) UNION ( SELECT EMPBREAKS.EMPID FROM EMPBREAKS WHERE ( ( TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') BETWEEN EMPBREAKS.STARTB AND EMPBREAKS.ENDB ) OR ( TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') BETWEEN EMPBREAKS.STARTB AND EMPBREAKS.ENDB ) OR ( EMPBREAKS.STARTB BETWEEN TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS' ) AND TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') ) OR ( EMPBREAKS.ENDB BETWEEN TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS') AND TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS') ) OR ( EMPBREAKS.FLAGCYCLIC =1 AND EMPBREAKS.DAYWEEKINDEX = 4 AND ( TO_DATE(TO_CHAR(EMPBREAKS.STARTB,'HH24:MI:SS'),'HH24:MI:SS') BETWEEN TO_DATE('11:00:00', 'HH24:MI:SS') AND TO_DATE('12:00:00', 'HH24:MI:SS') ) ) OR ( EMPBREAKS.FLAGCYCLIC =1 AND EMPBREAKS.DAYWEEKINDEX = 4 AND ( TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS'),'HH24:MI:SS') BETWEEN TO_DATE( '11:00:00', 'HH24:MI:SS') AND TO_DATE('12:00:00', 'HH24:MI:SS') ) ) OR ( EMPBREAKS.FLAGCYCLIC =1 AND EMPBREAKS.DAYWEEKINDEX = 4 AND ( TO_DATE('11:00:00', 'HH24:MI:SS') BETWEEN TO_DATE(TO_CHAR(EMPBREAKS.STARTB, 'HH24:MI:SS'),'HH24:MI:SS') AND TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS' ),'HH24:MI:SS') ) ) OR ( EMPBREAKS.FLAGCYCLIC =1 AND EMPBREAKS.DAYWEEKINDEX = 4 AND ( TO_DATE('12:00:00', 'HH24:MI:SS') BETWEEN TO_DATE(TO_CHAR(EMPBREAKS.STARTB, 'HH24:MI:SS', 'HH24:MI:SS')) AND TO_DATE(TO_CHAR(EMPBREAKS.ENDB,'HH24:MI:SS' ),'HH24:MI:SS')) ) ) ) ) UNION ( SELECT EMPSICKVACATIONS.EMP_NO FROM EMPSICKVACATIONS WHERE EMPSICKVACATIONS.VDATE = TO_DATE('19/06/2017 00:00:00', 'DD/MM/YYYY HH24:MI:SS') OR ( EMPSICKVACATIONS.CYCLICFLAG = 1 AND EMPSICKVACATIONS.WEEKDAYINDEX = 4 ) ) );

答案 2 :(得分:1)

你错过了前几个to_date的结尾括号:

TO_DATE('29/06/2017 11:00:00', 'DD/MM/YYYY HH24:MI:SS' BETWEEN SERVICES.STARTDATE AND SERVICES.ENDDATE) or  
TO_DATE('29/06/2017 12:00:00', 'DD/MM/YYYY HH24:MI:SS' BETWEEN SERVICES.STARTDATE AND SERVICES.ENDDATE) or

此外,看起来您正在尝试查看两个时段的开始日期和结束日期是否重叠 - 通常您可以使用以下方式执行此操作:

and period1.start_date <= period2.end_date
and period1.end_date >= period2.start_date

这更简单,更容易掌握,恕我直言。