【问题标题】:Oracle query fails with added COLLATE clauseOracle 查询失败并添加了 COLLATE 子句
【发布时间】:2020-05-11 20:57:14
【问题描述】:

在 sqlplus 中,此查询有效:

SQL> SELECT DISTINCT
  2  CNTPTY_TYPE
  3  FROM visn_exp.V_IHCVSN_CERT_DEP
  4  WHERE as_of_dt = '08-may-20'
  5  ;

CNTPTY_TYPE
----------------------------------------

Retail
PSE
Non-Financial Corporate
FI

但是这个失败了,带有 collat​​e 子句:

SQL> SELECT DISTINCT
  2  CNTPTY_TYPE COLLATE latin1_general_CI_AI AS CNTPTY_TYPE
  3  FROM VISN_EXP.V_IHCVSN_CERT_DEP
  4  WHERE as_of_dt = '08-may-20'
  5  ;
CNTPTY_TYPE COLLATE latin_general_CI_AI AS CNTPTY_TYPE
                    *
ERROR at line 2:
ORA-00923: FROM keyword not found where expected

我应该怎么做才能解决这个问题?

更新:在答案中尝试了建议的查询。得到了

SQL*Plus:2020 年 5 月 11 日星期一 21:03:20 发布 12.2.0.1.0 生产版

版权所有 (c) 1982、2017、甲骨文。保留所有权利。

输入密码: 上次成功登录时间:Mon May 11 2020 16:51:34 -04:00

连接到: Oracle Database 12c 企业版 12.1.0.2.0 - 64 位生产 具有分区、真实应用集群、自动存储管理、OLAP、 高级分析和实际应用测试选项

SQL> SELECT DISTINCT
  2  CNTPTY_TYPE COLLATE LATIN_AI AS CNTPTY_TYPE
  3  FROM VISN_EXP.V_IHCVSN_CERT_DEP
  4  WHERE as_of_dt = '08-may-20';
CNTPTY_TYPE COLLATE LATIN_AI AS CNTPTY_TYPE
                    *
ERROR at line 2:
ORA-00923: FROM keyword not found where expected

【问题讨论】:

  • 我必须承认我无法在 Oracle 中找到支持的排序规则列表,但不是 latin1_general_CI_AI 而不是 latin_general_CI_AI
  • 这也失败了,(更正了OP)
  • 什么版本的Oracle?
  • 我收到 ORA-12746:Oracle 18c 中无法识别的排序规则名称“LATIN1_GENERAL_CI_AI”。 Oracle 似乎不知道latin1_general。它必须是_CI_AI,而不是两者。这对我有用:COLLATE latin_AI。演示:dbfiddle.uk/…

标签: oracle collation


【解决方案1】:

一元运算符 COLLATE 仅在 Oracle 12.2 中引入,因此您会收到错误,因为您的版本是 12.1。

为什么您会收到错误“FROM 关键字未在预期的位置找到”,以及您在哪里找到它?因为在 Oracle 12.1 中,COLLATE 这个词没有特殊含义。在SELECT 子句中的列名之后找到它,Oracle 认为它是该列的别名。而且由于这个别名(无论如何它认为它是一个别名)后面没有逗号以供选择其他表达式,因此它需要关键字FROM。它会找到 LATIN_AI(或您最初尝试的任何内容)并且 那是它引发错误的地方 - 它期待 FROM 在那个地方。

12.1 中的解决方法?有一个,但它有缺点。 COLLATE 的好处是您可以在查询中指示排序规则,而不会影响您的整个会话。与在查询中调用TO_DATE 时使用日期格式模型相同,无需更改NLS_DATE_FORMAT

唉,在 12.1 中,您无法在查询级别控制排序规则;您必须为会话更改它(然后将其更改回来,如果您在会话中执行的其他查询或其他事情需要不同的排序规则)。你可以通过运行来做到这一点

alter session set nls_sort = 'LATIN_AI';

在运行查询之前。

如果您需要在运行此查询后恢复为“旧”nls_sort,您最好了解它是什么,将其更改为“LATIN_AI”之前。您可以通过在上面显示的alter session之前运行以下查询来做到这一点。

select value from v$nls_parameters where parameter = 'NLS_SORT';

然后,完成查询后,您需要再次运行 alter session 以将 nls_sort 更改回旧值。

旁注 - 为什么将日期与where 子句中的字符串进行比较? (或者as_of_date 是字符串数据类型 - 这是更糟糕的做法?)

【讨论】:

  • 正是我想要的!非常感谢!
【解决方案2】:

使用排序规则时,三个后缀会改变排序和比较的行为。

"_CI" : Case insensitive, but accent sensitive.
"_AI" : Both case and accent insensitive.
"_CS" : Both case and accent sensitive. This is default if no extension is used.

虽然不确定上面使用_general 的目的。但是,仅使用 LATIN_xx,将 xx 替换为上述任何选项都必须完成您的工作。

查询以检查拉丁语的有效NLS_SORT 值:-

SELECT * 
FROM V$NLS_VALID_VALUES 
WHERE parameter = 'SORT' and value = 'LATIN'; 

附加信息:Collations in Oracle

汇总查询:

SELECT DISTINCT
CNTPTY_TYPE COLLATE LATIN_AI AS CNTPTY_TYPE
FROM VISN_EXP.V_IHCVSN_CERT_DEP
WHERE as_of_dt = '08-may-20';

【讨论】:

  • 不高兴,我用你的查询更新了顶帖。
猜你喜欢
  • 1970-01-01
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
  • 1970-01-01
  • 2011-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多