【问题标题】:Database agnostic. ANSI SQL or ORM?数据库不可知论。 ANSI SQL 还是 ORM?
【发布时间】:2014-02-14 06:11:25
【问题描述】:

我在一个大部分代码都是用 PL/SQL 编写的项目中工作。我们需要重构代码以支持 SQL Server(如果将来可能与数据库无关)。他们决定将 PL SQL 代码转换为 ANSI SQL,但出于某种原因,这对我来说听起来不是一个好主意。

您能说说转换为 ANSI 而不是使用 ORM 的优缺点吗?

谢谢

【问题讨论】:

  • 对于这个一般性的问题,任何人都不可能提供权威的答案。也许实际需要并比较方式与另一种方式的有效性会很有用。

标签: sql orm plsql database-agnostic ansi-sql


【解决方案1】:

问题在于 pl/sql 不仅仅是 sql 语句。它有逻辑、类型、对象、函数、循环等等......

因此,虽然您可以将 sql 语句更改为与 ansi 兼容,但过程语言没有这样的动物。

你需要用某种独立的中间件语言重写 plsql,然后你就依赖它了。

此外,不同的数据库处理提交更改和锁定的方式不同,因此在编写代码时,开发人员需要了解这些差异。

【讨论】:

  • 我感觉自己像个顾问——为绿色检查和向上箭头工作。那将是一个向上箭头和一个绿色检查。还好我有一份日常工作。
  • “数据库不可知论”对于除了最简单的数据库应用程序之外的任何东西都是一个谬误。 @Brian 指出了陷阱。祝你好运。你会需要它。
【解决方案2】:

implement vendor agnostic (dynamic) procedural logic 的一种方法是使用第三方产品,如 jOOQ,您可以在其中编写如下内容:

ctx.begin(
    for_(i).in(1, 10).loop(
        insertInto(t).columns(c).values(i)
    )
).execute();

这将转化为(选择):

-- Db2
BEGIN
  DECLARE i integer;
  SET i = 1;
  WHILE i <= 10 DO
    INSERT INTO t (c)
    VALUES (i);
    SET i = (i + 1);
  END WHILE;
END
 
-- Firebird
EXECUTE BLOCK AS
  DECLARE i integer;
BEGIN
  :i = 1;
  WHILE (:i <= 10) DO BEGIN
    INSERT INTO t (c)
    VALUES (:i);
    :i = (:i + 1);
  END
END
 
-- MariaDB
BEGIN NOT ATOMIC
  FOR i IN 1 .. 10 DO
    INSERT INTO t (c)
    VALUES (i);
  END FOR;
END;
 
-- Oracle
BEGIN
  FOR i IN 1 .. 10 LOOP
    INSERT INTO t (c)
    VALUES (i);
  END LOOP;
END;
 
-- PostgreSQL
DO $$
BEGIN
  FOR i IN 1 .. 10 LOOP
    INSERT INTO t (c)
    VALUES (i);
  END LOOP;
END;
$$
 
-- SQL Server
BEGIN
  DECLARE @i int;
  BEGIN
    SET @i = 1;
    WHILE @i <= 10 BEGIN
      INSERT INTO t (c)
      VALUES (@i);
      SET @i = (@i + 1);
    END;
  END;
END;

您将被限制在 jOOQ 当前支持的最小公分母上,从 jOOQ 3.15 开始,它从 PL/SQL 中删除了一些功能(例如 RECORD 类型、TABLE 类型等。 ),但考虑到与 Oracle/SQL Server 无关的要求,这可能就足够了。

免责声明:我为 jOOQ 背后的供应商工作。

【讨论】:

    猜你喜欢
    • 2015-09-15
    • 1970-01-01
    • 2021-08-24
    • 2011-08-21
    • 2018-09-27
    • 2011-04-29
    • 2023-04-06
    • 2012-02-16
    • 1970-01-01
    相关资源
    最近更新 更多