49、数据库操作与互操作性全解析

数据库操作与互操作性全解析

1. 数据库索引创建

1.1 Oracle 索引创建

Oracle 允许在多种对象上创建索引,包括表、分区表、簇、索引组织表、类型化表或簇的标量对象以及嵌套表。可以指定索引的物理属性,还能选择是否并行创建索引。索引类型有普通 B - 树索引、部分索引、基于函数的索引、域索引和位图索引等。

为实现最大互操作性,应避免以下 Oracle 的 CREATE INDEX 语句变体:
- CREATE BITMAP INDEX
- INDEX TYPE IS index - type
- [NO]PARALLEL
- CLUSTER
- [NO]LOGGING
- [NO]COMPRESS
- [NO]SORT
- REVERSE
- ONLINE

此外,Oracle 支持表分区,且可使用 PCTFREE 子句模拟 SQL Server 的 FILLFACTOR PAD_INDEX 子句。

1.2 不同数据库创建视图

1.2.1 通用视图创建

视图是基于预定义查询结果集创建的虚拟表,在查询时呈现给用户。部分情况下,视图可用于检索数据库,还能对其基表进行插入、更新和删除操作。最具互操作性的 CREATE VIEW 语句形式如下:

CREATE VIEW view_name {[(column [,...])] |
AS 
subquery [WITH [CASCADED | LOCAL] CHECK OPTION]

WITH CASCADED CHECK OPTION WITH LOCAL CHECK OPTION 子句用于告知数据库管理系统(DBMS)在处理嵌套视图时的行为。使用前者时,对主视图进行插入、更新或删除操作时,会检查主视图及其依赖的所有视图;使用后者时,仅检查主视图。

1.2.2 各数据库视图创建特点
数据库 支持情况 注意事项
SQL Server 允许创建基本视图并带有一些额外选项。避免使用 WITH 选项,因为其他平台不支持视图加密、架构绑定或视图元数据选项。其 WITH CHECK OPTION 实现与标准的 WITH LOCAL CHECK OPTION 基本相同。
DB2 允许创建层次结构和面向对象的视图。为实现最大互操作性,应避免 OF type MODE DB2SQL REF IS UNDER parent_view INHERIT SELECT PRIVILEGES WITH common_table_expression 等子句。不支持物化视图(SQL Server 中的索引视图)。
MySQL 从 5.0 版本开始支持 ANSI 标准的 CREATE VIEW 语句。避免使用 ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE} 子句,且不允许对临时表创建视图,而 SQL Server 允许。
Oracle 支持丰富的 CREATE VIEW 语句子句。构建互操作性语句时,避免 [NO] FORCE OF type ... OF XMLTYPE ... 子句。 FORCE 子句可强制创建视图,忽略错误,类似于 SQL Server 中的延迟名称解析。支持标准的 WITH CHECK OPTION 子句及一些可选子子句,功能与标准的 WITH LOCAL CHECK OPTION 子句基本相同。允许使用 CREATE MATERIALIZED VIEW 语句创建物化视图,类似于 SQL Server 的索引视图。

1.3 创建触发器

1.3.1 通用触发器创建语法

所有数据库平台都支持以下通用的 CREATE TRIGGER 语句最低通用语法:

CREATE TRIGGER trigger_name
{BEFORE | AFTER} {DELETE | INSERT | UPDATE }
ON table_name
[FOR EACH {ROW | STATEMENT} ]
BEGIN
    statements
END

使用此通用语法,可设置触发器在实际的删除、插入或更新操作之前或之后触发(不能同时在两者时触发)。可选择指定触发器逻辑是针对事务中的每一行触发,还是针对事务中的每个语句触发。触发器可通过 OLD NEW 伪表访问操作前后的数据。

1.3.2 各数据库触发器创建特点
数据库 支持情况 注意事项
SQL Server 支持互操作性 CREATE TRIGGER 语句语法,有一些细微变化。触发器始终以 FOR EACH STATEMENT 模式运行,允许在单个语句中为多个事件创建单个触发器。使用 FOR 关键字代替 BEFORE 。避免使用 INSTEAD OF WITH ENCRYPTION WITH APPEND NOT FOR REPLICATION IF UPDATE... 子句。支持 INSTEAD OF 触发器,可通过 sp_settriggerorder 系统存储过程设置触发器触发顺序。将触发器伪表称为 DELETED INSERTED 。SQL Server 2005 支持 DDL 触发器事件。
DB2 支持互操作性 CREATE TRIGGER 语句语法,避免使用 MODE DB2SQL WHEN 条件子句。默认将两个伪表称为 OLD NEW ,可使用 REFERENCING 子句重命名。支持 INSTEAD OF 触发器类型,使用 NO CASCADE BEFORE 子句代替 BEFORE 。允许在给定表上创建多个触发器,按创建顺序触发。删除基表时不会自动删除触发器,需手动操作。
MySQL 支持互操作性版本的 CREATE TRIGGER 语句,但仅支持 FOR EACH ROW 子句。将触发器伪表称为 OLD NEW 。当前每个表每种时间和动作(如 BEFORE INSERT 触发器或 AFTER UPDATE 触发器)只允许有一个触发器。
Oracle 支持互操作性的 CREATE TRIGGER 语句,并增加了 INSTEAD OF 触发时间。将触发器伪表称为 OLD NEW ,可使用 REFERENCING 子句重命名。构建互操作性 CREATE TRIGGER 语句时,避免 [OR] 子句、 PARENT 子句和 WHEN 条件子句。允许特定关键字(如 DROP GRANT TRUNCATE )触发对象事件,可轻松转换为 SQL Server 2005 的 DDL 触发器。

1.4 创建存储过程和函数

大多数数据库平台支持创建存储过程和用户定义函数。由于 ANSI SQL 标准直到 2003 年才涉及过程扩展问题,各数据库平台通过创建自己的 SQL 方言来提供过程语言功能。

1.4.1 通用创建语法
  • 创建存储过程
CREATE PROCEDURE routine_name
( [{[IN | OUT | INOUT]} [parameter_name] data type [,...] ])
BEGIN
    routine_body
END
  • 创建函数
CREATE FUNCTION routine_name ([parameter[,...]])
( [{[IN | OUT | INOUT]} [parameter_name] data type [,...] ])
RETURNS scalar_value
BEGIN
    routine_body
END

参数可携带值进入例程( IN )、从例程输出( OUT )或两者兼具( INOUT )。函数必须返回单个标量值,存储过程可返回其他类型的值。为实现最大互操作性, routine_body 应仅包含 SQL 语句或过程调用。

1.4.2 各数据库支持情况
数据库 支持情况 注意事项
SQL Server 使用 T - SQL 方言,2005 年开始允许通过 CLR 接口将 .NET 语言(如 C#)编译为存储过程。允许存储过程返回结果集。支持 ENCRYPTION SCHEMABINDING 选项。
Oracle 使用 PL/SQL 方言和 Java。不允许存储过程返回结果集,需将重要结果集存储到临时表中。
DB2 允许使用第三代语言(如 C 和 Fortran)以及 SQL 和 ANSI 2003 SQL/PL 扩展语句。
MySQL 仅允许使用 SQL 存储过程和用户定义函数。

2. 数据库操作最佳实践

2.1 遵循 ANSI 标准

尽量遵循 ANSI 标准可提高代码的互操作性。尽管 SQL Server 本身并非完全符合 ANSI 标准,但这仍是一个重要原则。以下是一些最佳实践:
- 数据类型 :使用 ANSI 标准数据类型,避免使用 CURSOR IMAGE SQL_VARIANT TABLE VARCHAR(max) TEXT 等数据类型, DATETIME 数据类型在 SQL Server 中的实现与 ANSI 标准差异较大,也需谨慎使用。
- 标识符 :避免使用带引号、方括号或其他分隔符的标识符。
- 语句操作 :在使用 DELETE INSERT SELECT UPDATE 语句时,避免使用提示、非 ANSI 函数调用、 WITH 子句和 ANSI ONLY 子句。
- SQL Server 特定操作 :不使用 SQL Server 的第二个 FROM 子句实现 JOINS ,避免 INSERT...EXECUTE 语句。注意 SQL Server 的 SELECT 语句中有许多不具互操作性的子句,如 INTO 子句、 CUBE ROLLUP 子句、 COMPUTE 子句和 FOR XML 子句。
- 分区和索引 :除非仅与 SQL Server 和 Oracle 互操作,否则避免在数据库架构中使用分区。注意 SQL Server 的聚集索引与其他平台的“聚集”索引不同。
- 数据库例程 :数据库例程(过程、函数等)依赖于数据库平台的 SQL 方言,构建互操作性数据库例程通常需要大量迁移工作。

2.2 Codd 的 12 条关系数据库规则

2.2.1 规则概述

这些规则由 E. F. Codd 在 1985 年提出,用于定义关系数据库管理系统(RDBMS)应满足的更具体标准。以下是部分规则及 SQL Server 2005 的符合情况:
- 规则 1:信息规则 :关系数据库中的所有信息仅以一种方式表示,即表中的值。SQL Server 通常满足此规则,因为只能将信息存储在表中。
- 规则 2:保证访问规则 :每个数据项(原子值)可通过表名、主键值和列名的组合逻辑访问。SQL Server 严格遵循此规则,主键用于定位数据,通过表名、主键值和列名可准确访问数据。
- 规则 3:空值的系统处理规则 :完全关系型的 RDBMS 应支持不同数据类型的 NULL 值,用于表示缺失信息。 NULL 值在数学和字符串操作中应正确传播,即 NULL + <anything> = NULL 。SQL Server 有一些设置可自定义 NULL 值的处理方式:
- ANSI_NULLS :决定 NULL 值比较的处理方式。 OFF 时, NULL = NULL 比较结果为 True ON (默认)时,结果为 UNKNOWN
- CONCAT_NULL_YIELDS_NULL ON 时, NULL + 'String Value' = NULL OFF 时,为了与 SQL Server 早期版本兼容, NULL + 'String Value' = 'String Value'

2.3 总结

编写在 SQL Server 和其他主要数据库平台之间具有互操作性的代码时,会遇到诸多问题。无论是将代码从 SQL Server 2005 迁移到其他平台,还是反之,都可能需要修改代码以确保其正常运行。通过了解各数据库平台对不同语句的实现方式,可从一开始就编写更具互操作性和可移植性的代码。

通过遵循上述最佳实践和规则,可提高代码的互操作性,减少在不同数据库平台之间迁移代码时的工作量。在实际开发中,应根据具体需求和数据库平台的特点,合理选择和使用数据库功能。

2.4 操作步骤总结

为了更清晰地展示在不同数据库操作中的关键步骤,下面以表格形式总结创建索引、视图、触发器、存储过程和函数的操作步骤:
| 操作类型 | 通用步骤 | 各数据库特殊步骤 |
| ---- | ---- | ---- |
| 创建索引 | 1. 确定要创建索引的对象(表、分区表等)
2. 选择合适的索引类型(如 B - 树索引、位图索引等)
3. 指定索引的物理属性和是否并行创建 | Oracle:避免特定的 CREATE INDEX 语句变体;SQL Server 和 Oracle 可考虑分区索引 |
| 创建视图 | 1. 定义视图的查询语句
2. 根据需要选择是否使用 WITH CHECK OPTION 子句 | SQL Server:避免使用 WITH 选项;DB2:避免特定子句;MySQL:避免 ALGORITHM 子句;Oracle:避免特定子句 |
| 创建触发器 | 1. 确定触发器的触发时间( BEFORE AFTER )和触发事件( DELETE INSERT UPDATE
2. 指定触发器作用的表
3. 编写触发器逻辑 | SQL Server:使用 FOR 代替 BEFORE ,避免特定子句;DB2:避免特定子句,可重命名伪表;MySQL:仅支持 FOR EACH ROW ;Oracle:避免特定子句,支持 INSTEAD OF 触发时间 |
| 创建存储过程和函数 | 1. 定义例程的名称和参数
2. 确定参数的方向( IN OUT INOUT
3. 编写例程的主体逻辑 | SQL Server:支持 ENCRYPTION SCHEMABINDING 选项;Oracle:使用 PL/SQL 或 Java,不允许存储过程返回结果集;DB2:支持多种语言;MySQL:仅支持 SQL |

2.5 流程图展示

下面是一个创建存储过程的 mermaid 流程图,展示了通用的创建步骤:

graph LR
    A[开始] --> B[定义存储过程名称]
    B --> C[定义参数及方向]
    C --> D[编写存储过程主体逻辑]
    D --> E[结束创建]

2.6 实际应用案例

为了更好地理解上述数据库操作和互操作性的重要性,下面给出一个简单的实际应用案例。假设我们有一个跨平台的应用程序,需要在 SQL Server 和 Oracle 数据库之间迁移数据和代码。

2.6.1 数据迁移

在数据迁移过程中,首先要确保使用的是 ANSI 标准的数据类型,避免使用特定数据库的非标准数据类型。例如,将 SQL Server 中的 VARCHAR(max) 替换为 ANSI 标准的 VARCHAR 类型。

2.6.2 代码迁移

在迁移代码时,要根据各数据库的特点进行调整。例如,在创建视图时,需要避免使用不具互操作性的子句。以下是一个简单的视图创建代码示例,在 SQL Server 和 Oracle 中都能正常运行:

-- 创建视图
CREATE VIEW view_name
AS 
SELECT column1, column2
FROM table_name
WHERE condition;
2.6.3 触发器和存储过程迁移

对于触发器和存储过程,同样要遵循互操作性原则。例如,在创建触发器时,使用通用的 CREATE TRIGGER 语法:

-- 创建触发器
CREATE TRIGGER trigger_name
AFTER INSERT
ON table_name
BEGIN
    -- 触发器逻辑
    INSERT INTO another_table (column1, column2)
    VALUES (new_value1, new_value2);
END;

2.7 总结与展望

在数据库开发和管理中,实现代码的互操作性是一个重要的目标。通过遵循 ANSI 标准、了解各数据库平台的特点以及掌握通用的操作语法,可以有效地提高代码的可移植性和可维护性。

未来,随着数据库技术的不断发展,各数据库平台可能会进一步提高对标准的支持,减少差异。开发者也需要不断学习和适应这些变化,以更好地应对跨平台开发的挑战。同时,在实际项目中,要充分考虑数据库的性能、安全性等因素,综合运用各种数据库功能,为用户提供更高效、稳定的应用程序。

在实际工作中,建议开发者建立一个数据库操作的最佳实践文档,记录在不同数据库平台上的操作经验和注意事项,以便在后续项目中快速参考和应用。通过不断积累和总结,提高自己在数据库开发和管理方面的能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值