PostgreSQL Oracle兼容性 之 - parser SQL保留|关键字(keywrods)大全

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

标签

PostgreSQL , keywords , 关键字 , Oracle 兼容性


背景

PostgreSQL数据库中有哪些关键字,这些关键字的使用限制如何?

https://www.postgresql.org/docs/10/static/sql-keywords-appendix.html

文档中的说明并不是特别清晰,(并且KEYWORDS与版本强相关),所以使用pg_get_keywords这个系统函数得到的,更加准确可读。

https://www.postgresql.org/docs/10/static/functions-info.html

pg_get_keywords() returns a set of records describing the SQL keywords recognized by the server.   
  
1、The word column contains the keyword.   
2、The catcode column contains a category code:   
  U for unreserved, C for column name, T for type or function name, or R for reserved.  
3、The catdesc column contains a possibly-localized string describing the category.  

关键字查找

keyword不同的分类,含义不一样。

postgres=# select * from pg_get_keywords();  
       word        | catcode |                   catdesc                      
-------------------+---------+----------------------------------------------  
 abort             | U       | unreserved  
 absolute          | U       | unreserved  
 access            | U       | unreserved  
 action            | U       | unreserved  
 add               | U       | unreserved  
 admin             | U       | unreserved  
.............  

例子,使用keywrod作为identity的报错示例:

postgres=# \set VERBOSITY verbose  
postgres=# create table cast (id int);  
ERROR:  42601: syntax error at or near "cast"  
LINE 1: create table cast (id int);  
                     ^  
LOCATION:  scanner_yyerror, scan.l:1086  

注意:keyword的分类解释

1、unreserved,不保留,可以用于任何identity(视图、表、函数、类型、索引、字段、类型 等名称)。

2、reserved,保留,不可用于任何identity。

3、reserved (can be function or type name),保留,但是可用于函数、类型名。

4、unreserved (cannot be function or type name),不保留,但是不可用于函数、类型名。

理解了这几类意思,你就知道keyword什么地方能用,什么地方不能用了。

keyword相关代码

src/backend/utils/adt/misc.c

/* Function to return the list of grammar keywords */  
Datum  
pg_get_keywords(PG_FUNCTION_ARGS)  
{  
..........  
                switch (ScanKeywords[funcctx->call_cntr].category)  
                {  
                        case UNRESERVED_KEYWORD:  
                                values[1] = "U";  
                                values[2] = _("unreserved");  
                                break;  
                        case COL_NAME_KEYWORD:  
                                values[1] = "C";  
                                values[2] = _("unreserved (cannot be function or type name)");  
                                break;  
                        case TYPE_FUNC_NAME_KEYWORD:  
                                values[1] = "T";  
                                values[2] = _("reserved (can be function or type name)");  
                                break;  
                        case RESERVED_KEYWORD:  
                                values[1] = "R";  
                                values[2] = _("reserved");  
                                break;  
                        default:                        /* shouldn't be possible */  
                                values[1] = NULL;  
                                values[2] = NULL;  
                                break;  
                }  
...........  

src/include/common/keywords.h

/* Keyword categories --- should match lists in gram.y */  
#define UNRESERVED_KEYWORD              0  
#define COL_NAME_KEYWORD                1  
#define TYPE_FUNC_NAME_KEYWORD  2  
#define RESERVED_KEYWORD                3  

src/include/parser/kwlist.h

/* name, value, category */  
PG_KEYWORD("abort", ABORT_P, UNRESERVED_KEYWORD)  
PG_KEYWORD("absolute", ABSOLUTE_P, UNRESERVED_KEYWORD)  
PG_KEYWORD("access", ACCESS, UNRESERVED_KEYWORD)  
PG_KEYWORD("action", ACTION, UNRESERVED_KEYWORD)  
....................  
PG_KEYWORD("xmlparse", XMLPARSE, COL_NAME_KEYWORD)  
PG_KEYWORD("xmlpi", XMLPI, COL_NAME_KEYWORD)  
PG_KEYWORD("xmlroot", XMLROOT, COL_NAME_KEYWORD)  
PG_KEYWORD("xmlserialize", XMLSERIALIZE, COL_NAME_KEYWORD)  
PG_KEYWORD("xmltable", XMLTABLE, COL_NAME_KEYWORD)  
PG_KEYWORD("year", YEAR_P, UNRESERVED_KEYWORD)  
PG_KEYWORD("yes", YES_P, UNRESERVED_KEYWORD)  
PG_KEYWORD("zone", ZONE, UNRESERVED_KEYWORD)  

plpgsql中的保留字

src/pl/plpgsql/src/pl_scanner.c

/*  
 * A word about keywords:  
 *  
 * We keep reserved and unreserved keywords in separate arrays.  The  
 * reserved keywords are passed to the core scanner, so they will be  
 * recognized before (and instead of) any variable name.  Unreserved words  
 * are checked for separately, usually after determining that the identifier  
 * isn't a known variable name.  If plpgsql_IdentifierLookup is DECLARE then  
 * no variable names will be recognized, so the unreserved words always work.  
 * (Note in particular that this helps us avoid reserving keywords that are  
 * only needed in DECLARE sections.)  
 *  
 * In certain contexts it is desirable to prefer recognizing an unreserved  
 * keyword over recognizing a variable name.  In particular, at the start  
 * of a statement we should prefer unreserved keywords unless the statement  
 * looks like an assignment (i.e., first token is followed by ':=' or '[').  
 * This rule allows most statement-introducing keywords to be kept unreserved.  
 * (We still have to reserve initial keywords that might follow a block  
 * label, unfortunately, since the method used to determine if we are at  
 * start of statement doesn't recognize such cases.  We'd also have to  
 * reserve any keyword that could legitimately be followed by ':=' or '['.)  
 * Some additional cases are handled in pl_gram.y using tok_is_keyword().  
 *  
 * We try to avoid reserving more keywords than we have to; but there's  
 * little point in not reserving a word if it's reserved in the core grammar.  
 * Currently, the following words are reserved here but not in the core:  
 * BEGIN BY DECLARE EXECUTE FOREACH IF LOOP STRICT WHILE  
 */  
  
/*  
 * Lists of keyword (name, token-value, category) entries.  
 *  
 * !!WARNING!!: These lists must be sorted by ASCII name, because binary  
 *               search is used to locate entries.  
 *  
 * Be careful not to put the same word in both lists.  Also be sure that  
 * pl_gram.y's unreserved_keyword production agrees with the second list.  
 */  
..........  
static const ScanKeyword reserved_keywords[] = {  
        PG_KEYWORD("all", K_ALL, RESERVED_KEYWORD)  
        PG_KEYWORD("begin", K_BEGIN, RESERVED_KEYWORD)  
        PG_KEYWORD("by", K_BY, RESERVED_KEYWORD)  
        PG_KEYWORD("case", K_CASE, RESERVED_KEYWORD)  
        PG_KEYWORD("declare", K_DECLARE, RESERVED_KEYWORD)  
        PG_KEYWORD("else", K_ELSE, RESERVED_KEYWORD)  
        PG_KEYWORD("end", K_END, RESERVED_KEYWORD)  
        PG_KEYWORD("execute", K_EXECUTE, RESERVED_KEYWORD)  
        PG_KEYWORD("for", K_FOR, RESERVED_KEYWORD)  
        PG_KEYWORD("foreach", K_FOREACH, RESERVED_KEYWORD)  
        PG_KEYWORD("from", K_FROM, RESERVED_KEYWORD)  
        PG_KEYWORD("if", K_IF, RESERVED_KEYWORD)  
        PG_KEYWORD("in", K_IN, RESERVED_KEYWORD)  
        PG_KEYWORD("into", K_INTO, RESERVED_KEYWORD)  
        PG_KEYWORD("loop", K_LOOP, RESERVED_KEYWORD)  
        PG_KEYWORD("not", K_NOT, RESERVED_KEYWORD)  
        PG_KEYWORD("null", K_NULL, RESERVED_KEYWORD)  
        PG_KEYWORD("or", K_OR, RESERVED_KEYWORD)  
        PG_KEYWORD("strict", K_STRICT, RESERVED_KEYWORD)  
        PG_KEYWORD("then", K_THEN, RESERVED_KEYWORD)  
        PG_KEYWORD("to", K_TO, RESERVED_KEYWORD)  
        PG_KEYWORD("using", K_USING, RESERVED_KEYWORD)  
        PG_KEYWORD("when", K_WHEN, RESERVED_KEYWORD)  
        PG_KEYWORD("while", K_WHILE, RESERVED_KEYWORD)  
};  
  
...........  
  
static const ScanKeyword unreserved_keywords[] = {  
        PG_KEYWORD("absolute", K_ABSOLUTE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD)  
        PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD)  
        PG_KEYWORD("assert", K_ASSERT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("backward", K_BACKWARD, UNRESERVED_KEYWORD)  
        PG_KEYWORD("close", K_CLOSE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("collate", K_COLLATE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("column", K_COLUMN, UNRESERVED_KEYWORD)  
        PG_KEYWORD("column_name", K_COLUMN_NAME, UNRESERVED_KEYWORD)  
        PG_KEYWORD("constant", K_CONSTANT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("constraint", K_CONSTRAINT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("constraint_name", K_CONSTRAINT_NAME, UNRESERVED_KEYWORD)  
        PG_KEYWORD("continue", K_CONTINUE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("current", K_CURRENT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("cursor", K_CURSOR, UNRESERVED_KEYWORD)  
        PG_KEYWORD("datatype", K_DATATYPE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("debug", K_DEBUG, UNRESERVED_KEYWORD)  
        PG_KEYWORD("default", K_DEFAULT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("detail", K_DETAIL, UNRESERVED_KEYWORD)  
        PG_KEYWORD("diagnostics", K_DIAGNOSTICS, UNRESERVED_KEYWORD)  
        PG_KEYWORD("dump", K_DUMP, UNRESERVED_KEYWORD)  
        PG_KEYWORD("elseif", K_ELSIF, UNRESERVED_KEYWORD)  
        PG_KEYWORD("elsif", K_ELSIF, UNRESERVED_KEYWORD)  
        PG_KEYWORD("errcode", K_ERRCODE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("error", K_ERROR, UNRESERVED_KEYWORD)  
        PG_KEYWORD("exception", K_EXCEPTION, UNRESERVED_KEYWORD)  
        PG_KEYWORD("exit", K_EXIT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("fetch", K_FETCH, UNRESERVED_KEYWORD)  
        PG_KEYWORD("first", K_FIRST, UNRESERVED_KEYWORD)  
        PG_KEYWORD("forward", K_FORWARD, UNRESERVED_KEYWORD)  
        PG_KEYWORD("get", K_GET, UNRESERVED_KEYWORD)  
        PG_KEYWORD("hint", K_HINT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("import", K_IMPORT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("info", K_INFO, UNRESERVED_KEYWORD)  
        PG_KEYWORD("insert", K_INSERT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("is", K_IS, UNRESERVED_KEYWORD)  
        PG_KEYWORD("last", K_LAST, UNRESERVED_KEYWORD)  
        PG_KEYWORD("log", K_LOG, UNRESERVED_KEYWORD)  
        PG_KEYWORD("message", K_MESSAGE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("message_text", K_MESSAGE_TEXT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("move", K_MOVE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("next", K_NEXT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("no", K_NO, UNRESERVED_KEYWORD)  
        PG_KEYWORD("notice", K_NOTICE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("open", K_OPEN, UNRESERVED_KEYWORD)  
        PG_KEYWORD("option", K_OPTION, UNRESERVED_KEYWORD)  
        PG_KEYWORD("perform", K_PERFORM, UNRESERVED_KEYWORD)  
        PG_KEYWORD("pg_context", K_PG_CONTEXT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("pg_datatype_name", K_PG_DATATYPE_NAME, UNRESERVED_KEYWORD)  
        PG_KEYWORD("pg_exception_context", K_PG_EXCEPTION_CONTEXT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("pg_exception_detail", K_PG_EXCEPTION_DETAIL, UNRESERVED_KEYWORD)  
        PG_KEYWORD("pg_exception_hint", K_PG_EXCEPTION_HINT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("print_strict_params", K_PRINT_STRICT_PARAMS, UNRESERVED_KEYWORD)  
        PG_KEYWORD("prior", K_PRIOR, UNRESERVED_KEYWORD)  
        PG_KEYWORD("query", K_QUERY, UNRESERVED_KEYWORD)  
        PG_KEYWORD("raise", K_RAISE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("relative", K_RELATIVE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("result_oid", K_RESULT_OID, UNRESERVED_KEYWORD)  
        PG_KEYWORD("return", K_RETURN, UNRESERVED_KEYWORD)  
        PG_KEYWORD("returned_sqlstate", K_RETURNED_SQLSTATE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("reverse", K_REVERSE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("row_count", K_ROW_COUNT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("rowtype", K_ROWTYPE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("schema", K_SCHEMA, UNRESERVED_KEYWORD)  
        PG_KEYWORD("schema_name", K_SCHEMA_NAME, UNRESERVED_KEYWORD)  
        PG_KEYWORD("scroll", K_SCROLL, UNRESERVED_KEYWORD)  
        PG_KEYWORD("slice", K_SLICE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("sqlstate", K_SQLSTATE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("stacked", K_STACKED, UNRESERVED_KEYWORD)  
        PG_KEYWORD("table", K_TABLE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("table_name", K_TABLE_NAME, UNRESERVED_KEYWORD)  
        PG_KEYWORD("type", K_TYPE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("use_column", K_USE_COLUMN, UNRESERVED_KEYWORD)  
        PG_KEYWORD("use_variable", K_USE_VARIABLE, UNRESERVED_KEYWORD)  
        PG_KEYWORD("variable_conflict", K_VARIABLE_CONFLICT, UNRESERVED_KEYWORD)  
        PG_KEYWORD("warning", K_WARNING, UNRESERVED_KEYWORD)  
};  

如何强制使用保留字keyword

对于identity,可以使用双引号,强制使用关键字。

postgres=# create table "cast" (id int);  
CREATE TABLE  
  
postgres=# select * from "cast";  
 id   
----  
(0 rows)  

参考

《PostgreSQL Oracle 兼容性之 - 系统列(关键字、保留字)的处理(ctid, oid, cmin, cmax, xmin, xmax)》

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
22天前
|
SQL 存储 Oracle
Oracle的PL/SQL定义变量和常量:数据的稳定与灵动
【4月更文挑战第19天】在Oracle PL/SQL中,变量和常量扮演着数据存储的关键角色。变量是可变的“魔术盒”,用于存储程序运行时的动态数据,通过`DECLARE`定义,可在循环和条件判断中体现其灵活性。常量则是不可变的“固定牌”,一旦设定值便保持不变,用`CONSTANT`声明,提供程序稳定性和易维护性。通过 `%TYPE`、`NOT NULL`等特性,可以更高效地管理和控制变量与常量,提升代码质量。善用两者,能优化PL/SQL程序的结构和性能。
|
2月前
|
Oracle 关系型数据库 分布式数据库
PolarDB常见问题之PolarDB(Oracle兼容版) 执行命令报错如何解决
PolarDB是阿里云推出的下一代关系型数据库,具有高性能、高可用性和弹性伸缩能力,适用于大规模数据处理场景。本汇总囊括了PolarDB使用中用户可能遭遇的一系列常见问题及解答,旨在为数据库管理员和开发者提供全面的问题指导,确保数据库平稳运行和优化使用体验。
|
2月前
|
关系型数据库 分布式数据库 数据库
PolarDB PostgreSQL版:Oracle兼容的高性能数据库
PolarDB PostgreSQL版是一款高性能的数据库,具有与Oracle兼容的特性。它采用了分布式架构,可以轻松处理大量的数据,同时还支持多种数据类型和函数,具有高可用性和可扩展性。它还提供了丰富的管理工具和性能优化功能,为企业提供了可靠的数据存储和处理解决方案。PolarDB PostgreSQL版在数据库领域具有很高的竞争力,可以满足各种企业的需求。
|
2月前
|
SQL 存储 关系型数据库
SQL的基本语法以及SQL语句的关键字的使用,SELECT、INSERT、UPDATE、DELETE、CREATE、ALTER、DROP等。
SQL的基本语法以及SQL语句的关键字的使用,SELECT、INSERT、UPDATE、DELETE、CREATE、ALTER、DROP等。
|
4月前
|
SQL Oracle 关系型数据库
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
94 0
|
11天前
|
SQL 关系型数据库 数据库
SQL 42501: Postgresql查询中的权限不足错误
SQL 42501: Postgresql查询中的权限不足错误
|
16天前
|
人工智能 Oracle 关系型数据库
一篇文章弄懂Oracle和PostgreSQL的Database Link
一篇文章弄懂Oracle和PostgreSQL的Database Link
|
22天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
|
22天前
|
SQL Oracle 安全
Oracle的PL/SQL循环语句:数据的“旋转木马”与“无限之旅”
【4月更文挑战第19天】Oracle PL/SQL中的循环语句(LOOP、EXIT WHEN、FOR、WHILE)是处理数据的关键工具,用于批量操作、报表生成和复杂业务逻辑。LOOP提供无限循环,可通过EXIT WHEN设定退出条件;FOR循环适用于固定次数迭代,WHILE循环基于条件判断执行。有效使用循环能提高效率,但需注意避免无限循环和优化大数据处理性能。掌握循环语句,将使数据处理更加高效和便捷。
|
22天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL条件控制:数据的“红绿灯”与“分岔路”
【4月更文挑战第19天】在Oracle PL/SQL中,IF语句与CASE语句扮演着数据流程控制的关键角色。IF语句如红绿灯,依据条件决定程序执行路径;ELSE和ELSIF提供多分支逻辑。CASE语句则是分岔路,按表达式值选择执行路径。这些条件控制语句在数据验证、错误处理和业务逻辑中不可或缺,通过巧妙运用能实现高效程序逻辑,保障数据正确流转,支持企业业务发展。理解并熟练掌握这些语句的使用是成为合格数据管理员的重要一环。

相关产品

  • 云原生数据库 PolarDB
  • 推荐镜像

    更多