验证Oracle列名称

时间:2018-01-04 07:11:57

标签: oracle oracle11g

在一个场景中,我们动态地动态创建sql到create临时表。 table_name没有问题,因为它由我们决定,但是列名由不在我们控制中的源提供。

通常我们会使用以下查询检查列名:

select  ..
where NOT REGEXP_LIKE (Column_Name_String,'^([a-zA-Z])[a-zA-Z0-9_]*$') 
OR Column_Name_String is NULL
OR Length(Column_Name_String) > 30

然而,是否有任何内置功能可以进行更广泛的检查。此外,欢迎上述查询的任何输入。

提前致谢。

基于以下答案的最终查询:

select  ..
where NOT REGEXP_LIKE (Column_Name_String,'^([a-zA-Z])[a-zA-Z0-9_]{0,29}$') 
OR Column_Name_String is NULL
OR Upper(Column_Name_String) in (select Upper(RESERVED_WORDS.Keyword) from V$RESERVED_WORDS RESERVED_WORDS)

特别不喜欢字符中的字符,例如列名中的$因此无法使用..

dbms_assert.simple_sql_name('VALID_NAME')

相反,使用正则表达式,我可以决定允许使用自己的一组字符。

2 个答案:

答案 0 :(得分:4)

这个答案不一定提供性能或逻辑改进,但您实际上可以使用单个正则表达式验证列名称:

SELECT ...
WHERE NOT
    REGEXP_LIKE (COALESCE(Column_Name_String, ''), '^([a-zA-Z])[a-zA-Z0-9_]{0,29}$')

这是因为:

  • 它使用相同的模式匹配列,即以字母开头,之后仅使用字母数字字符和下划线
  • NULL列名称映射到空字符串,这使得正则表达式
  • 失败
  • 我们使用长度量词{0,29}来直接检查正则表达式中的列长度

答案 1 :(得分:3)

  

"是否有任何功能可以进行更广泛的检查。"

Oracle具有DBMS_ASSERT.SIMPLE_SQL_NAME()功能。如果符合Oracle命名规则,则返回传递的名称...

 select dbms_assert.simple_sql_name('VALID_NAME') from dual;

...如果名称无效,则投掷ORA-44003

有效名称允许任何字符,如果名称是双引号(yuck,但那么创建"临时表格在线")。此功能也不会检查名称的长度,因此您仍需要自己验证。

Find out more in the docs.

此处还有a SQL Fiddle

  

"创建一个带有注释列的表是不可能的,因为它是一个无效的标识符"

公平点。 DBMS_ASSERT主要用于防止SQL注入。因此,它验证值是否符合Oracle的命名规则,而不是该值是有效的Oracle名称。要抓住comment之类的内容,您还需要针对V$RESERVED_WORDS检查值,可能是where reserved != 'Y'。由于这是一个V$视图,因此默认情况下不会授予它;如果您无法访问,则需要请求友好的DBA提供帮助。

  

"为了验证列名,我相信我应该检查整个列表"

由你决定。区别在于某些关键字可以合法地用作标识符。例如,当TYPE引入对象关系的东西时,它只成为Oracle版本8中的保留字。但是现有系统中有很多表和视图使用'TYPE'作为列名(尤其是Oracle数据字典)。如果Oracle使TYPE成为一个适当保留的单词,那么它将破坏所有这些系统。因此,不能用作标识符的保留字列表是所有Oracle关键字的子集。

关于一般任务的意见:

  

"我们从外部源(文件)获取数据,程序/脚本的工作是将数据推送到oracle表。"

这项任务分为两部分。

首先,您应该与第三方商定这些文件的标准格式。不需要发现文件'结构或内容。 (或者如果有这样的需要,因为文件是从第三方的轮播中随机获取的,你可能不应该使用关系数据库,而是其他东西:Endeca?Python Pandas库?)

第二个是即时创建表格。如果您有一个商定的文件结构,那么您应该根据您的具体情况使用SQL*Loaderexternal tables加载到标准表中。如果你在12c上,可能会感兴趣SQL*Loader Express Mode