9

我的公司让我为 Python ORM 完成 Oracle 的后端。我很惊讶 RDBMS 做事情的方式有多么不同,即使是简单的东西。我学到了很多关于 Oracle 和其他 RDBMS 之间差异的知识。纯粹出于好奇,我想了解更多。

在将 SQL 从一个平台移植到另一个平台方面,有哪些常见的“陷阱”?

请,每个答案只有一个陷阱。

4

17 回答 17

4

Oracle 似乎没有游标的问题,它们在 SQL Server 中是一个巨大的性能问题。

实际上,几乎所有性能调整都是特定于数据库的(这就是为什么 ANSII 标准代码与设计成特定于数据库的特定 SQL 风格的更好方法相比通常执行得非常差的原因)。

日期是另一件事,似乎从数据库到数据库的处理方式非常不同。

数据类型也不等价。倾向于让 SQL Server 新手的一件事是时间戳数据类型与日期和时间完全无关,并且不能转换为数据时间值。

于 2009-06-30T15:11:40.160 回答
2

Oracle 将不允许您插入空字符串:它们被默默地转换为 NULL。

于 2009-06-30T14:26:20.327 回答
2

Oracle 不允许选择没有 FROM 子句的语句。因此,您不能进行这样的查询:

SELECT 1

相反,您必须说查询来自DUAL表:

SELECT 1 FROM DUAL
于 2009-06-30T14:05:19.683 回答
2

另一个例子是生成唯一(通常是代理)主键。

许多数据库,如 SQL Server 和 sqlite 允许将列声明为标识:通常,如果插入时缺少该列的值,数据库将为该列生成唯一值。

相比之下,Oracle 是否创建了一个与表分开的序列,然后在序列上使用 nextval 来生成下一个值:

CREATE SEQUENCE test_seq;
SELECT test_seq.nextval FROM dual;

或者,更典型的是:

INSERT INTO foo(id, title) VALUES (test_seq.nextval, 'bar');
于 2009-06-30T14:14:28.323 回答
2

在将 SQL 从一个平台移植到另一个平台方面,有哪些常见的“陷阱”?

与通过将字典单词直接替换为短语来尝试翻译 from Englishto相同。Russian

你好再见工作,但因为玛丽有一只小羊羔而对莎士比亚无话可说。

不同RDBMS的有不同的文化,尽管有SQL他们的名字。

例如,行限制。

Oracle

WHERE rownum = 1

SQL Server

SELECT TOP 1

MySQLPostgreSQL

LIMIT 1

DB2

SELECT * ... FETCH FIRST 1 ROW ONLY

四个不同的子句

于 2009-06-30T14:17:06.617 回答
2

多值 IN 子句查询。我过去一直在 Oracle 上使用这些,并且惊讶地发现您不能在 SQL Server 中执行此操作。例如,这个查询:

SELECT * FROM mytable WHERE (col1, col2) IN ( SELECT col1, col2 FROM othertable )
于 2009-06-30T14:19:09.187 回答
2

Oracle 对引用的处理方式与 MySQL 不同。

MySQL: `object_name`, 'string', "string"
Oracle: "object_name", 'string'

此外,逃避是不同的。

MySQL: 'It\'s easy'
Oracle: 'It''s slightly confusing'

(请注意,要在 Oracle 中转义除引号之外的任何内容,您可以在查询中使用 ESCAPE 指令;SELECT * FROM testTable WHERE percent = '50\%' ESCAPE '\')

于 2009-06-30T14:57:55.100 回答
2

我在移植时遇到的 SQL Server 和 Oracle 之间的差异列表:

认为 ANSI 标准 SQL 在数据库之间是完全可移植的?再想想。

编写 ANSI 标准 SQL 不实用

于 2009-06-30T15:24:03.877 回答
1

我记得一个让我完全措手不及的特殊 Oracle 问题。我不确定这是实例的配置还是默认设置,但我们在 IN 语句中不能有超过 1000 个元素。所以我们不得不欺骗它做想做的事:

SELECT Col1,Col2 
FROM Table
WHERE Code IN (1,2,3,...,1000)
OR Code IN (1001,1002,1003,...,2000)

等等

丑陋,但它的工作。

(在有人指出子查询或内联视图的明显解决方案之前,查询是在完全不同的系统上生成的)

于 2009-07-05T17:59:08.887 回答
1

Oracle 不允许您在一个查询中进行多次插入。MySQL 允许这样做:

INSERT INTO test(id, name) VALUES (1, 'foo'),(2, 'bar');
于 2009-06-30T14:51:04.007 回答
1

性能问题是一个大问题。例如,根据 AFAIK,Oracle 中的视图几乎与表一样快。当我不得不使用 SQLServer 时,情况并非如此。这些视图有效地扼杀了性能,使相同的选择减慢了一个数量级或更多(直接从表中查询需要 0.5 秒,而使用视图可能需要一分钟)。它们的使用也有很多限制,例如并非所有 SQL 函数都可以在视图上使用。

请注意,这在 6 年前的 5-6 年是正确的,我不知道微软从那以后是否对此进行了改进。

于 2009-06-30T14:19:42.917 回答
1

晦涩的连接语法,如 Oracle 用于外连接的 (+) 语法。在我曾经工作过的一家公司,到处都在使用这种语法,而不是标准的 LEFT OUTER JOIN / LEFT JOIN 语法,这使得将一些东西移植到 MySQL 上非常痛苦。

于 2009-06-30T14:24:25.900 回答
1

临时表 - Oracle 与 SQL Server/MySQL。从 Oracle 过渡到 MS/MySQL,没问题。反过来,就有点不一样了。

于 2009-07-03T13:35:32.847 回答
1

对于产品特定陷阱的全局,您需要了解逻辑数据库设计和物理数据库设计之间的区别。

逻辑数据库设计主要与表的特性有关。表的特征包括列和约束。尽管表本身是物理的,但表设计通常可以从一个数据库系统移植到另一个数据库系统。某些数据类型的工作方式存在差异,语法也存在一些差异,例如是否可以在表名中使用下划线。但是一个好的逻辑设计应该从一个系统移植到另一个系统,只需进行微小的更改或没有更改。

物理数据库设计主要与表结构所依赖的基础设施的特性有关。几乎所有系统都支持索引,默认的索引类型是 B-tree,尽管它可能被称为别的东西。但从那时起,每个系统都有自己的物理特征,从一个系统到另一个系统可能完全不同。Oracle 的一个典型物理特性是表空间。与表空间密切相关的是表和表空间之间的映射。物理设计必须在系统特定的基础上进行。

除了您使用的 RDM 系统之外,您还需要在设计中考虑数据量、负载、响应时间要求以及磁盘等系统资源。好消息是,可以在不更改应用程序代码的情况下对物理设计进行大量更改。这称为物理数据独立性。这意味着在编写了一些应用程序代码并加载了一些数据之后,您可以在一定程度上自由地调整和调整物理设计。

您可能想查看一些有关数据库设计的书籍,以更深入地了解逻辑和物理设计以及它们之间的区别。一些受欢迎的作者是 CJ Date 和 Joe Celko。

于 2009-07-03T14:00:12.600 回答
0

设置运营商支持。

除了 UNION / UNION ALL 之外,跨数据库的集合运算符支持相当参差不齐。Oracle 和 SQL Server 支持其中的大多数,但 Oracle 支持 MINUS 操作以及等效的标准 EXCEPT DISTINCT 操作。AFIK,MySQL 仅支持 UNION(不支持 INTERSECT 或 EXCEPT)。

于 2009-06-30T14:42:57.923 回答
0

我不确定这在 Python 附带的驱动程序中是否正确,但在我使用的“可怕”版本中,如果结果集中的列对列中的所有值返回 NULL,则列本身不会返回结果集的结构。这可能(并且经常发生)导致无法在开发中复制的生产错误。

由于您要离开 Oracle,所以这不应该是一个问题,但是开发人员使用一个关键字来缓解我怀疑 MySQL 支持的这个“功能”。不过,我忘记了它是什么,谷歌也没有提供帮助。

于 2009-06-30T14:56:14.433 回答
0

不同的数据库处理二进制数据略有不同。例如,这将在 MySQL 下工作:

mysql> CREATE TABLE t (c BINARY(3));
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t SET c = 'z';
Query OK, 1 row affected (0.01 sec)

但是,Oracle 依赖这些值为十六进制的值:

SQL> CREATE TABLE t (c RAW(3));

Table created.

SQL> INSERT INTO t VALUES ('z');
INSERT INTO t VALUES ('z')
                 *
ERROR at line 1:
ORA-01465: invalid hex number

相反,我们必须将其转换为十六进制:

SQL> INSERT INTO t VALUES (rawtohex('z'));

1 row created.
于 2009-06-30T14:07:47.667 回答