Oracle兼容-语法-GLOBAL|PRIVATE TEMPORARY TABLE


1. 语法

  1. SET sql_mode = ORACLE;
  2. create_temporary_table:
  3. create_global_temporary | create_private_temporary
  4. create_global_temporary:
  5. CREATE GLOBAL TEMPORARY TABLE
  6. [ schema . ] table_ident [ ( relational_properties ) ]
  7. [ ON COMMIT { DELETE | PRESERVE } ROWS ]
  8. table_properties
  9. create_private_temporary:
  10. CREATE PRIVATE TEMPORARY TABLE
  11. [ schema . ] table_ident [ ( relational_properties ) ]
  12. [ ON COMMIT { DROP | PRESERVE } DEFINITION ]
  13. table_properties

需要先切换到 ORACLE 模式下才能支持本语法。

2. 定义和用法

GreatSQL中支持创建 GLOBAL|PRIVATE 两种不同的临时表。

    1. 创建GLOBAL TEMPORARY TABLE
    • 会立即创建一个临时表定义,但不会立即创建临时表实体。
    • 具体创建时机为SQL语句有插入的操作时。若创建后,在当时的SQL没有插入任何记录,则会在该SQL结束时,删除该临时表实例。
    • ON COMMIT 子句指定 DELETE ROWS 时,表示在当前事务结束时,会删除该临时表实例;
    • ON COMMIT 子句指定 PRESERVE ROWS 时,则在当前事务结束时,会保留该临时表实例及内容。
    • 当省略 ON COMMIT 子句时,默认为 DELETE ROWS
    • 当前连接会话结束时,会删除该临时表实例。
    • 执行 TRUNCATE 语句也会删除该临时表实例。
    • 当系统内有任何该临时表的实例创建时,不可以对该临时表进行DDL操作,例如:ALTER TABLE, CREATE INDEX等操作。
    • 执行 DROP TABLE 可以立即删除当前会话该临时表实例(若存在的话)及临时表定义。若是由其他会话创建该临时表的实例时,则只会删除当前会话的临时表实例,并会在删除临时表定义时报错。
    • 执行 SHOW CREATE TABLE 可以显示当前会话是否已经创建临时表实例。若当前会话存在该临时表实例时(例如:对该表有写入数据), 此时会显示为 CREATE TEMPORARY TABLE,不带 ``GLOBAL` 标识。
    1. 创建PRIVATE TEMPORARY TABLE
    • 会立即创建一个临时表。
    • ON COMMIT 子句指定 DROP DEFINITION 时,表示在当前事务结束时,会删除该临时表
    • ON COMMIT 子句指定 PRESERVE DEFINITION 时,则在当前事务结束时,会保留该临时表。
    • 当省略 ON COMMIT 子句时,默认为 DROP DEFINITION
    • 当前会话结束时,会删除该临时表。
    • 执行 DROP TABLE 会删除该临时表。

3. Oracle兼容说明

  1. 临时表的维护及使用,是基于GreatSQL的临时表。因此任一临时表都只能在当前语句中被引用一次。例如:t1是临时表,则 SELECT * FROM t1 UNION SELECT * FROM t1 会报错,见下方详细案例。
  2. 在MGR环境中,其中一个节点创建临时表实例时,在其他节点的DDL操作并不会被锁阻塞,只会依照目前MGR环境中的DDL操作规则,对临时表定义进行操作。
  3. 与GreatSQL临时表相同,SHOW TABLES 命令不会显示已创建的 GLOBAL|PRIVATE TEMPORARY TABLE 临时表实例。
  4. 如果同时使用GreatSQL原生的 TEMPORARY TABLE 创建同名的 GLOBAL TEMPORARY TABLE,会让后续SQL语句以原生的 TEMPORARY TABLE 为主。
  5. 与GreatSQL常规临时表支持的数据类型一致,当临时表中包含 BLOB 类型列时不会报错。
  6. 不支持对 GLOBAL TEMPORARY TABLE 创建触发器。但触发器及视图内可以引用 GLOBAL TEMPORARY TABLE
  7. 执行 RENAME TABLEALTER TABLE .. RENAME 语句时,必须当时没有 GLOBAL TEMPORARY TABLE 临时表同名实例(Oracle 沒有這個限制)。
  8. 每个 GLOBAL TEMPORARY TABLE 实例的 AUTO_INCREMENT 字段都一律由1开始(Oracle没这个约束)。
  9. 当创建临时表实例后,在任何会话中删除 GLOBAL TEMPORARY TABLE 所在的数据库时,该临时表实例会继续存在。若之后继续创建同名的数据库及同名的 GLOBAL TEMPORARY TABLE,并不会对已经生成的临时表实例有影响。
  10. 由于在 PRIVATE TEMPORARY TABLE 中是不支持指定主键的,因此在创建 PRIVATE TEMPORARY TABLE 时不能显式指定主键,也必须设置 sql_generate_invisible_primary_key=0,避免隐式创建主键,否则会提示不支持该用法。
  11. 执行 TRUNCATE 语句会终止当前事务,会对当前事务中创建的临时表有影响。

4. 示例

  1. greatsql> SET sql_mode = ORACLE;
  2. greatsql> CREATE TEMPORARY TABLE t1 (id INT);
  3. Query OK, 0 rows affected (0.01 sec)
  4. greatsql> INSERT INTO t1 VALUES (1);
  5. Query OK, 1 row affected (0.00 sec)
  6. -- 1. 普通临时表在同一个SQL语句中,只能被引用一次
  7. greatsql> SELECT * FROM t1 UNION SELECT * FROM t1;
  8. ERROR 1137 (HY000): Can not reopen table: 't1'
  9. greatsql> SELECT * FROM t1;
  10. +------+
  11. | id |
  12. +------+
  13. | 1 |
  14. +------+
  15. 1 row in set (0.01 sec)
  16. -- 2. 创建GLOBAL TEMPORARY TABLE,指定不同的ON COMMIT子句
  17. -- 先切换到ORACLE模式下
  18. greatsql> SET sql_mode = ORACLE;
  19. greatsql> CREATE GLOBAL TEMPORARY TABLE gtt1 (
  20. id INT PRIMARY KEY,
  21. c1 VARCHAR(16));
  22. -- 不指定ON COMMIT子句,默认为DELETE ROWS
  23. greatsql> SHOW CREATE TABLE gtt1\G
  24. *************************** 1. row ***************************
  25. Table: gtt1
  26. Create Table: CREATE GLOBAL TEMPORARY TABLE "gtt1" (
  27. "id" int NOT NULL,
  28. "c1" varchar(16) DEFAULT NULL,
  29. PRIMARY KEY ("id")
  30. ) ON COMMIT DELETE ROWS ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  31. -- 指定ON COMMIT PRESERVE ROWS
  32. greatsql> CREATE GLOBAL TEMPORARY TABLE gtt2 (
  33. id INT PRIMARY KEY,
  34. c1 VARCHAR(16)
  35. ) ON COMMIT PRESERVE ROWS;
  36. greatsql> SHOW CREATE TABLE gtt2\G
  37. *************************** 1. row ***************************
  38. Table: gtt2
  39. Create Table: CREATE GLOBAL TEMPORARY TABLE "gtt2" (
  40. "id" int NOT NULL,
  41. "c1" varchar(16) DEFAULT NULL,
  42. PRIMARY KEY ("id")
  43. ) ON COMMIT PRESERVE ROWS ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  44. greatsql> INSERT INTO gtt1 SELECT 1, 'c11' FROM DUAL;
  45. Query OK, 0 rows affected (0.40 sec)
  46. Records: 1 Duplicates: 0 Warnings: 0
  47. -- 上面的SQL中未显式启用事务,SQL执行结束后等于事务也结束了,所以查询不到数据
  48. greatsql> SELECT * FROM gtt1;
  49. Empty set (0.00 sec)
  50. greatsql> INSERT INTO gtt2 SELECT 1, 'c12' FROM DUAL;
  51. Query OK, 0 rows affected (0.04 sec)
  52. Records: 1 Duplicates: 0 Warnings: 0
  53. -- SQL语句执行结束后还能查询到数据
  54. greatsql> SELECT * FROM gtt2;
  55. +----+------+
  56. | id | c1 |
  57. +----+------+
  58. | 1 | c12 |
  59. +----+------+
  60. 1 row in set (0.00 sec)
  61. -- 再次查看DDLgtt1不变
  62. greatsql> SHOW CREATE TABLE gtt1\G
  63. *************************** 1. row ***************************
  64. Table: gtt1
  65. Create Table: CREATE GLOBAL TEMPORARY TABLE "gtt1" (
  66. "id" int NOT NULL,
  67. "c1" varchar(16) DEFAULT NULL,
  68. PRIMARY KEY ("id")
  69. ) ON COMMIT DELETE ROWS ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  70. 1 row in set (0.00 sec)
  71. -- 再次查看DDLgtt2变成了普通临时表
  72. greatsql> SHOW CREATE TABLE gtt2\G
  73. *************************** 1. row ***************************
  74. Table: gtt2
  75. Create Table: CREATE TEMPORARY TABLE "gtt2" (
  76. "id" int NOT NULL,
  77. "c1" varchar(16) DEFAULT NULL,
  78. PRIMARY KEY ("id")
  79. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  80. 1 row in set (0.00 sec)
  81. -- 3. 显式开启事务测试
  82. greatsql> DELETE FROM gtt1;
  83. greatsql> DELETE FROM gtt2;
  84. greatsql> BEGIN;
  85. greatsql> INSERT INTO gtt1 SELECT 1, 'c11' FROM DUAL;
  86. greatsql> INSERT INTO gtt2 SELECT 1, 'c12' FROM DUAL;
  87. -- 此时事务尚未提交,gtt1表能查询到数据
  88. greatsql> SELECT * FROM gtt1;
  89. +----+------+
  90. | id | c1 |
  91. +----+------+
  92. | 1 | c11 |
  93. +----+------+
  94. 1 row in set (0.00 sec)
  95. greatsql> SELECT * FROM gtt2;
  96. +----+------+
  97. | id | c1 |
  98. +----+------+
  99. | 1 | c12 |
  100. +----+------+
  101. 1 row in set (0.00 sec)
  102. -- 再次查看DDL,发现都变成了普通临时表
  103. greatsql> SHOW CREATE TABLE gtt1\G
  104. *************************** 1. row ***************************
  105. Table: gtt1
  106. Create Table: CREATE TEMPORARY TABLE "gtt1" (
  107. "id" int NOT NULL,
  108. "c1" varchar(16) DEFAULT NULL,
  109. PRIMARY KEY ("id")
  110. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  111. 1 row in set (0.00 sec)
  112. greatsql> SHOW CREATE TABLE gtt2\G
  113. *************************** 1. row ***************************
  114. Table: gtt2
  115. Create Table: CREATE TEMPORARY TABLE "gtt2" (
  116. "id" int NOT NULL,
  117. "c1" varchar(16) DEFAULT NULL,
  118. PRIMARY KEY ("id")
  119. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  120. 1 row in set (0.00 sec)
  121. -- 提交事务后再次查询数据,发现gtt1表被清空
  122. greatsql> COMMIT;
  123. greatsql> SELECT * FROM gtt1;
  124. Empty set (0.00 sec)
  125. greatsql> SELECT * FROM gtt2;
  126. +----+------+
  127. | id | c1 |
  128. +----+------+
  129. | 1 | c12 |
  130. +----+------+
  131. 1 row in set (0.00 sec)
  132. -- 再次查看DDLgtt1恢复成GLOBAL TEMPORARY TABLEgtt2继续保持普通临时表
  133. greatsql> SHOW CREATE TABLE gtt1\G
  134. *************************** 1. row ***************************
  135. Table: gtt1
  136. Create Table: CREATE GLOBAL TEMPORARY TABLE "gtt1" (
  137. "id" int NOT NULL,
  138. "c1" varchar(16) DEFAULT NULL,
  139. PRIMARY KEY ("id")
  140. ) ON COMMIT DELETE ROWS ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  141. greatsql> SHOW CREATE TABLE gtt2\G
  142. *************************** 1. row ***************************
  143. Table: gtt2
  144. Create Table: CREATE TEMPORARY TABLE "gtt2" (
  145. "id" int NOT NULL,
  146. "c1" varchar(16) DEFAULT NULL,
  147. PRIMARY KEY ("id")
  148. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  149. -- 3. 创建PRIVATE TEMPORARY TABLE,指定不同的ON COMMIT子句,
  150. -- 3.1 指定PRESERVE DEFINITION子句
  151. greatsql> SET sql_mode = ORACLE;
  152. greatsql> CREATE PRIVATE TEMPORARY TABLE ora$ptt_s1(
  153. id INT,
  154. c1 VARCHAR(30)
  155. )ON COMMIT PRESERVE DEFINITION;
  156. greatsql> INSERT INTO ora$ptt_s1 VALUES (1, 'ora$ptt_s1-1');
  157. greatsql> INSERT INTO ora$ptt_s1 VALUES (2, 'ora$ptt_s1-2');
  158. -- 查看table
  159. greatsql> SHOW CREATE TABLE ora$ptt_s1\G
  160. *************************** 1. row ***************************
  161. Table: ora$ptt_s1
  162. Create Table: CREATE PRIVATE TEMPORARY TABLE "ora$ptt_s1" (
  163. "id" int DEFAULT NULL,
  164. "c1" varchar(30) DEFAULT NULL
  165. ) ON COMMIT PRESERVE DEFINITION ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  166. -- 查询数据
  167. greatsql> SELECT * FROM ora$ptt_s1;
  168. +------+--------------+
  169. | id | c1 |
  170. +------+--------------+
  171. | 1 | ora$ptt_s1-1 |
  172. | 2 | ora$ptt_s1-2 |
  173. +------+--------------+
  174. 2 rows in set (0.00 sec)
  175. -- 3.2 指定DROP DEFINITION子句
  176. -- 开始事务
  177. greatsql> BEGIN;
  178. -- 不指定ON COMMIT子句默认使用DROP DEFINITION
  179. greatsql> CREATE PRIVATE TEMPORARY TABLE ora$ptt_t0(
  180. id INT,
  181. c1 VARCHAR(30)
  182. );
  183. greatsql> CREATE PRIVATE TEMPORARY TABLE ora$ptt_t1(
  184. id INT,
  185. c1 VARCHAR(30)
  186. ) ON COMMIT DROP DEFINITION;
  187. -- 写入数据
  188. greatsql> INSERT INTO ora$ptt_t0 VALUES (10, 'ora$ptt_t0-10');
  189. greatsql> INSERT INTO ora$ptt_t0 VALUES (20, 'ora$ptt_t0-20');
  190. greatsql> INSERT INTO ora$ptt_t1 VALUES (100, 'ora$ptt_t1-100');
  191. greatsql> INSERT INTO ora$ptt_t1 VALUES (200, 'ora$ptt_t1-200');
  192. -- 查看表DDL
  193. greatsql> SHOW CREATE TABLE ora$ptt_t0\G
  194. *************************** 1. row ***************************
  195. Table: ora$ptt_t0
  196. Create Table: CREATE PRIVATE TEMPORARY TABLE "ora$ptt_t0" (
  197. "id" int DEFAULT NULL,
  198. "c1" varchar(30) DEFAULT NULL
  199. ) ON COMMIT DROP DEFINITION ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  200. greatsql> SHOW CREATE TABLE ora$ptt_t1\G
  201. *************************** 1. row ***************************
  202. Table: ora$ptt_t1
  203. Create Table: CREATE PRIVATE TEMPORARY TABLE "ora$ptt_t1" (
  204. "id" int DEFAULT NULL,
  205. "c1" varchar(30) DEFAULT NULL
  206. ) ON COMMIT DROP DEFINITION ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  207. -- 查询数据
  208. greatsql> SELECT * FROM ora$ptt_t1;
  209. +------+----------------+
  210. | id | c1 |
  211. +------+----------------+
  212. | 100 | ora$ptt_t1-100 |
  213. | 200 | ora$ptt_t1-200 |
  214. +------+----------------+
  215. 2 rows in set (0.00 sec)
  216. -- 提交事务
  217. greatsql> COMMIT;
  218. -- 查询数据
  219. greatsql> SELECT * FROM ora$ptt_s1;
  220. +------+--------------+
  221. | id | c1 |
  222. +------+--------------+
  223. | 1 | ora$ptt_s1-1 |
  224. | 2 | ora$ptt_s1-2 |
  225. +------+--------------+
  226. 2 rows in set (0.00 sec)
  227. -- 事务提交后,PRIVATE TEMPORARY TABLE会被删除
  228. greatql> SELECT * FROM ora$ptt_t0;
  229. ERROR 1146 (42S02): Table 'greatsql.ora$ptt_t0' doesn't exist
  230. greatsql> SELECT * FROM ora$ptt_t1;
  231. ERROR 1146 (42S02): Table 'greatsql.ora$ptt_t1' doesn't exist
  232. -- 显式指定PRIMARY KEY,或者当sql_generate_invisible_primary_key=1时会报告不支持
  233. greatsql> CREATE PRIVATE TEMPORARY TABLE ora$ptt_t1(
  234. id INT,
  235. c1 VARCHAR(30),
  236. PRIMARY KEY(id));
  237. ERROR 7561 (HY000): unsupported feature with temporary table
  238. greatsql> SET sql_generate_invisible_primary_key = 1;
  239. greatsql> CREATE PRIVATE TEMPORARY TABLE ora$ptt_t1(
  240. id INT,
  241. c1 VARCHAR(30));
  242. ERROR 7561 (HY000): unsupported feature with temporary table

问题反馈

联系我们

扫码关注微信公众号

greatsql-wx