【DB.PostgreSQL】省略PostgreSQL的SQL语句中的双引号

本文深入探讨了PostgreSQL如何处理数据库对象名的大小写,包括创建大写对象名的方法及其对查询的影响,并提供了一些建议来避免潜在的问题。

转自:http://blog.sina.com.cn/s/blog_4fb490ff01012g5f.html


标准的SQL是不区分大小写的。但是PostgreSQL对于数据库中对象的名字允许使用支持大小写区分的定义和引用方法。方式就是在DDL中用双引号把希望支持大小的对象名括起来。

比如希望创建一个叫AAA的表。如果用CREATE TABLE AAA (...);的话,创建出来的表实际上是aaa。

如果希望创建大写的AAa表的话,就需要用CREATE TABLE "AAA" (...);这种双引号的方式定义对象名。

这样写的缺点是查询语句必须也使用双引号的方式引用对象名。比如SELECT * FROM "AAA";否则PostgreSQL缺省会去找aaa这个对象,然后返回aaa不存在的错误。需要注意的是不仅仅是表可以这样定义和引用,对PostgreSQL中的任意对象(比如列名,索引名等)都有效。

实际上传统的SQL都是不区分大小写的,所以只要DDL和DLL按照传统(不使用双引号)的方式操作数据库对象不会有任何问题。问题出在如果表是通过PostgreSQL的pgAdmin III 工具创建的话,缺省是按照有双引号的方式创建对象的,所以DLL里面必须也要按照有双引号的方式使用。但是这种写法不是标准的,如果是通过一些通用库函数访问数据库的话,会不被支持。

建议:

1.不推荐使用pgAdmin III这个工具创建数据库对象。还是应该手工编写DDL语句

2.不推荐在DDL里用双引号的方式创建区分大小写的对象

3.PostgreSQL给出的建议是SQL的key word用大写,其他的名称全部使用小写。

<think>嗯,用户这次想了解不同数据中完全限定SQL名的语法规则。这个问题很实用,尤其对需要跨数据开发或迁移项目的用户来说特别重要。用户可能是个后端工程师或DBA,正在处理多数据环境下的兼容性问题。从用户提供的引用材料来看,虽然引用内容不完全匹配需求,但[^1]提到了远程的引用方式,[^2]展示了FlinkSQL的CREATETABLE语法,这些都暗示了名结构的重要性。真正的价值在于如何归纳不同数据系统的共性差异。关于完全限定名,核心都是“层级标识符”的串联,但不同DBMS的层级名称差别很大。比如SQLServer的四段式结构(服务器.数据.模式.名)和PostgreSQL的三段式(数据.模式.名)就不能混淆。更复杂的场景还有特殊字符的转义规则——MySQL要用反引号,而SQLServer必须用方括号,这个细节一旦出错就会导致脚本崩溃。用户没有明说但可能关心的是:是否所有数据都强制要求完全限定名?这需要分情况说明。在单数据单schema场景下通常不需要,但涉及跨服务器查询(如SQLServer的链接服务器)或跨数据查询(如PostgreSQL的FDW)时就必须完整指定。这点值得展开,毕竟用户引用的[^1]里提到了远程实例访问,可能暗示他正在处理分布式数据访问问题。比较有趣的是开源数据的差异点:MySQL允许在完全限定名中省略中间层级(如mydb..mytable跳过schema),但SQLite这种轻量级数据根本不需要层级结构。Oracle的特殊之处在于必须用服务名代替服务器名,这个特例要单独强调。最后要注意提示大小写敏感性这个“暗坑”,毕竟Linux平台的PostgreSQL默认区分大小写。用户如果是从Windows环境迁移过来的,很可能在这里栽跟头。可以在示例中用不同的特殊字符转义方式演示这个风险点。</think> 好的,完全限定名(Fully Qualified Table Name)在SQL中用于精确指定数据中的特定,确保在涉及多个数据、模式、服务器或同名的不同对象时能无歧义地引用。其语法结构在不同关系型数据管理系统(RDBMS)中存在差异,以下是主要数据的规则总结: **核心结构模式 (通常由多级标识符组成):** 1. **SQL Server & Azure SQL Database (T-SQL):** * **最高层级:** SQL Server实例/链接服务器名称。 * **中间层级:** 数据名称、模式名称 (`dbo` 是最常见的默认模式)。 * **最低层级:** 名称。 * **标准语法:** ```sql [服务器名\实例名].[数据名].[模式名].[名] ``` * **常见场景下的简化:** * **当前连接的服务器实例内:** ```sql [数据名].[模式名].[名] ``` * **当前连接数据内 (指定模式):** ```sql [模式名].[名] ``` * **默认模式下 (通常是 dbo):** ```sql [名] -- 最简形式,不完全是限定名 ``` * **引号:** 如果名称包含空格、特殊字符或需要区分大小写(在区分大小写的服务器/数据上),必须用方括号 `[]` 或双引号 `""` 包裹各部分。`[]` 在 T-SQL 中最常用。 * **示例:** `SELECT * FROM [ADV-PROD\ERP].[SalesDB].[dbo].[Orders];` (引用 `ADV-PROD\ERP` 服务器上 `SalesDB` 数据中 `dbo` 模式的 `Orders` ) [^1][^5]。 2. **MySQL:** * **结构:** ```sql `数据名`.`名` ``` * **层级:** 不直接支持跨物理服务器实例(需要通过FEDERATED引擎、复制或应用逻辑处理)。 * **无显式模式(Schema):** MySQL 中的 `CREATE DATABASE` 相当于其他数据的 `CREATE SCHEMA`。`DATABASE` 和 `SCHEMA` 关键字在 MySQL 中是同义词。 * **引号:** 如果名称包含空格、特殊字符或需要区分大小写(在区分大小写的文件系统上,如 Linux),使用反引号 **`` ` ``** 包裹。 * **示例:** ```sql SELECT * FROM `inventory`.`products`; ``` (引用当前服务器实例上 `inventory` 数据中的 `products` )。 3. **PostgreSQL:** * **标准语法:** ```sql "数据名"."模式名"."名" ``` * **层级:** 通常在同一服务器集群(包含多个逻辑数据)内工作。 * **模式(Schema)关键:** `public` 是默认模式。 * **跨数据访问:** 原生不支持直接跨数据查询同一个集群中的不同数据。需要使用外部数据包装器 (`postgres_fdw`) 或 `dblink` 扩展。 * **引号:** 双引号 **`"`** 用于包裹包含大写字母、空格、特殊字符或需要强制区分大小写的标识符。默认情况下,PostgreSQL 在内部会将不带引号的名称转换为小写。 * **示例:** `SELECT * FROM "CustomerData"."public"."Invoices";` (引用 `CustomerData` 数据中 `public` 模式的 `Invoices` )。 4. **Oracle Database:** * **结构 (跨越数据链接时):** ```sql "名"@"数据链接名" ``` * **本地完全限定名 (在同一个数据实例内):** 模式拥有对象。 ```sql "模式名"."名" ``` * **数据链接 (DB Link):** 用于访问远程数据中的对象。 * **引号:** 双引号 **`"`** 包裹强制区分大小写、包含空格或特殊字符的标识符。Oracle 默认将不带引号的标识符转为大写。 * **示例:** * `SELECT * FROM SCOTT.EMP;` (引用当前数据实例中 `SCOTT` 用户的 `EMP` ,模式名大写)。 * `SELECT * FROM "SalesData"@"RemoteDB";` (通过名为 `RemoteDB` 的数据链接访问远程服务器上 `SalesData` 用户的 - 假设该名无引号创即为大写,故不需引号) [^4] (其概念类似 SQL Server 的链接服务器)。 5. **SQLite:** * **简单性:** 一般使用名本身即可,因为 SQLite 通常附着单个数据文件。 * **附着多个数据:** 允许在一个会话中 `ATTACH DATABASE` 其他数据文件。 * **完全限定名语法 (跨ATTACHED数据时):** ```sql [数据别名].[名] ``` * **模式:** SQLite 没有真正的模式概念(`main`, `temp` 是特殊命名空间,可看作模式别名)。 * **引号:** 使用方括号 **`[]`**、双引号 **`"`** 或反引号 **`` ` ``** 包裹包含空格或特殊字符的名称。 * **示例:** `SELECT * FROM main.Users;` (引用主数据中的 `Users` ) 或 `SELECT * FROM backup_db.Employees;` (引用 `ATTACH` 的别名为 `backup_db` 的数据中的 `Employees` )。 6. **H2 Database:** * **结构与 PostgreSQL 类似:** ```sql [数据名].[模式名].[名] ``` * **模式:** 支持模式。 * **跨数据访问:** 在嵌入式模式下通常使用单个数据文件;服务器模式类似,但主要在一个数据连接内操作。`CREATE LINKED TABLE` 或 `SCRIPT RUNFROM` 可用于某种程度的交互。 * **引号:** 使用双引号 **`"`** 包裹强制区分大小写、包含空格或特殊字符的标识符。 * **示例:** `SELECT * FROM "PUBLIC"."Customers";` (区分大小写) 或 `SELECT * FROM PUBLIC.CUSTOMERS;` (非区分大小写)。 7. **Apache Spark SQL:** * **Hive Metastore Catalog (常见):** ```sql [catalog_name].[database_name].[table_name] ``` * **Catalog:** 元数据的顶层容器(例如 `hive_metastore`, `iceberg_catalog`)。`spark_catalog` 通常是默认的系统 Catalog。 * **Database:** 传统意义上的数据或模式(`Schema`)。 * **Table:** 名。 * **直接文件系统/对象存储路径 (不使用 Metastore):** ```sql delta.`/path/to/table` ``` * **引号:** 反引号 **`` ` ``** 包裹带特殊字符或空格的标识符。 * **JDBC 数据源:** Spark 写入 JDBC 目标时 (`jdbcDF.write.jdbc`) 的完全限定名依赖于目标数据(如 SQL Server, PostgreSQL)的规则,通常在参数 `dbtable` 中指定,支持引号包裹 (如 `"schema"."table"`) [^4]。 * **示例:** `SELECT * FROM hive_metastore.sales.orders;` (引用 Hive Metastore Catalog 中 `sales` 数据的 `orders` ) 或 `SELECT * FROM delta.`abfss://container@account.dfs.core.windows.net/data/delta/events`;` [^2]。 **通用要点 & 注意事项:** 1. **引号 (Quoting/Identifier Delimiters):** 这是**最重要的区别点之一**。务必使用目标数据要求的特定引号(`` ` `` for MySQL, `""` for PostgreSQL/Oracle, `[]` for SQL Server)来包裹包含特殊字符、空格、或需要强制区分大小写的标识符。错误使用引号是跨数据兼容性问题的主要来源。 2. **大小写敏感性 (Case Sensitivity):** * SQL Server:默认实例名、数据名、对象名(名、列名等)**不区分大小写**(除非安装时指定了区分大小写的排序规则)。 * PostgreSQL/Oracle:**数据引擎内部标识符默认不区分大小写**(存储小写或在查询时转换为大写/小写比较),但**带引号的标识符区分大小写**。 * MySQL:**在 Windows/macOS 上文件系统不区分大小写时,名存储和比较通常不区分大小写**;在 Linux(区分大小写的文件系统)上,名**区分大小写**;数据名和别名**总是区分大小写**(在 Linux上文件系统也区分大小写)。 * 务必了解目标数据平台及其文件系统的默认大小写行为。 3. **何时需要完全限定名?** * 引用**不同数据**中的 (SQL Server, MySQL, Spark Catalog)。 * 引用**不同模式**中的 (PostgreSQL, Oracle, SQL Server, Spark Database/Schema)。 * 引用**不同服务器/实例**中的 (SQL Server via Linked Server, Oracle via DB Link)。 * 避免**对象名称冲突**(当连接范围/当前上下文中有多个同名的时)。 * 在动态SQL或复杂脚本中**提高明确性和可维护性**。 4. **连接上下文 (Current Context):** 在数据客户端中,连接的当前数据(`USE database_name;`)决定了未限定的 `database_name` 部分;当前用户的默认模式(`SEARCH_PATH` in PostgreSQL, default schema in SQL Server)决定了未限定的 `schema_name` 部分。完全限定名不受当前上下文影响。 5. **性能:** 使用完全限定名不会带来性能开销。数据解析语句时会确定对象位置。 **总结关键区别:** | 数据 | 完全限定名标准语法 (远程/多数据场景) | 默认引号 | 特殊注意事项 | | :-------------- | :-------------------------------------------------- | :--------------- | :------------------------------------------------- | | **SQL Server** | `[服务器\实例].[数据].[模式].[]` | `[]` | 链接服务器访问 | | **MySQL** | `` `数据`.`` `` | `` ` `` | 无模式;跨实例需特殊处理;平台决定大小写敏感性 | | **PostgreSQL** | `"数据"."模式".""` (通常同实例) | `"` | 强模式;跨数据需 `postgres_fdw` / `dblink` | | **Oracle** | `"模式".""` (本地) / `""@数据链接` (远程) | `"` | 强模式;跨数据DB Links;默认标识符大写 | | **SQLite** | `[数据别名].[]` (`ATTACH` 后) | `[]` `"` `` ` `` | 简单,无原生模式;多文件靠别名 | | **Spark SQL** | `[catalog_name].[database_name].[table_name]` | `` ` `` | Catalog概念;支持路径和 Metastore | | **H2** | `[数据名].[模式名].[名]` | `"` | 嵌入式通常单文件 | **核心议:** 在编写需要跨数据运行的脚本、工具或文档时,始终查阅目标数据的官方文档,重点关注其**标识符引用规则**和**对象限定层次结构**。明确指定模式(在支持的数据中)并使用正确的引号包裹标识符是保证可移植性和避免错误的关键。 **相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值