Oracle陷入了经验丰富的新事物

时间:2009-07-30 20:10:27

标签: php mysql sql-server oracle postgresql

对于刚接触平台的人来说,Oracle有什么问题,但对于关系数据库(MySQL,MS SQL Server,Postgres等)来说并不陌生。

我正在寻找的那种事情的两个例子

  1. 许多关系数据库产品处理为您创建auto_increment密钥。 Oracle没有,您必须手动创建序列,然后创建触发器

  2. 通过SQL Developer界面插入数据时,必须手动提交数据

  3. PHP相关陷阱的奖励积分,因为这是假设有经验的newb将使用的平台我将

8 个答案:

答案 0 :(得分:23)

注意:我只在这里解释陷阱,我。即Oracle表现不像其他系统那样的情况。 Oracle比其他RDBMS有许多好处,但它们不是帖子的主题。

  • 如果没有SELECT,您就无法FROM

    SELECT  1
    

    会失败,你需要:

    SELECT  1
    FROM    dual
    
  • 空字符串和NULL是一回事。

    SELECT  *
    FROM    dual
    WHERE   '' = ''
    

    什么都不返回。

  • 既没有TOP也没有LIMIT。您可以在WHERE子句中限制结果:

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    正是这样,使用子查询,因为在ROWNUM之前评估了ORDER BY

  • 您不能将相关子查询嵌套多个深度级别。这个会失败:

    SELECT  (
            SELECT  *
            FROM    (
                    SELECT  dummy
                    FROM    dual di
                    WHERE   di.dummy = do.dummy
                    ORDER BY
                            dummy
                    )
            WHERE   rownum = 1
            )
    FROM    dual do
    

    这是一个问题。

  • NULL值未编入索引。此查询不会使用索引进行排序:

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    ,除非col被标记为NOT NULL

    请注意,未编入索引的是NULL ,而不是。您可以在可空列上创建索引,非NULL值将进入索引。

    但是,当查询条件假定NULL值可能满足时,将不会使用索引。

    在上面的示例中,您希望返回所有值(包括NULL s)。然后索引不知道非NULL值,因此无法检索它们。

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    但是这个查询将使用索引:

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            WHERE   col IS NOT NULL
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    ,因为非NULL值不能满足条件。

  • 默认情况下,NULL是最后排序的,而非排在第一位(如PostgreSQL中所示,但与MySQLSQL Server不同)

    此查询:

    SELECT  *
    FROM    (
            SELECT  1 AS id
            FROM    dual
            UNION ALL
            SELECT  NULL AS id
            FROM    dual
            ) q
    ORDER BY
            id
    

    将返回

    id
    ---
    1
    NULL
    

    要像SQL ServerMySQL一样进行排序,请使用:

    SELECT  *
    FROM    (
            SELECT  1 AS id
            FROM    dual
            UNION ALL
            SELECT  NULL AS id
            FROM    dual
            ) q
    ORDER BY
            id NULLS FIRST
    

    请注意,它会中断rownum次序,除非后者未在子查询中使用(如上所述)

  • "MYTABLE""mytable"(双引号重要)是不同的对象。

    SELECT  *
    FROM    mytable -- wihout quotes
    

    将从前者中选择,而不是后者。如果前者不存在,则查询将失败。

    CREATE TABLE mytable
    

    创建"MYTABLE",而不是"mytable"

  • Oracle中,所有隐式锁(由DML操作产生)都是行级的,永远不会升级。也就是说,没有受到事务影响的行可以被隐式锁定。

    作家永远不会阻止读者(反之亦然)。

    要锁定整个表,您应该发出明确的LOCK TABLE语句。

    行锁存储在数据页上。

  • Oracle中,没有“CLUSTERED索引”,有“索引组织表”。默认情况下,表是堆组织的(与SQL Server不同,MySQLInnoDB不同。

    Oracle世界中,“群集存储”意味着组织多个表,以便共享公共密钥(来自多个表)的行也共享数据页。

    单个数据页承载多个表中的多行,这使得此键上的连接速度非常快。

答案 1 :(得分:4)

SELECT 1不会工作,请从双重选择1。

如果你使用分层数据,那么连接就很棒。

答案 2 :(得分:2)

一条评论:您不必为了使用序列而创建触发器,除非您坚持复制Sybase / SQL Server IDENTITY列的行为。我发现在实际的插入语句中直接使用序列更有用,例如

INSERT
  INTO MyTable
     ( KeyCol
     , Name
     , Value
     )
SELECT Seq_MyTable.NextVal
     , 'some name'
     , 123
  FROM dual;

您无需担心触发器执行的开销,并且您可以灵活地处理将行插入表中而无需担心分配的序列值(例如将数据从架构移动到另一个时) 。您还可以从序列中预先选择值,以插入数据范围和IDENTITY功能难以或不可能的其他技术。

答案 3 :(得分:1)

SQL Server 相比,我似乎遇到了更多对架构对象和数据敏感的Oracle数据库。

答案 4 :(得分:1)

不要忘记在行集中任何可能完全填充空值的列周围使用nvl(列)。否则,行集中将缺少该列。

这是对的,完全错过了!

示例:

SELECT nvl(employeeName,'Archie'), nvl(employeeSpouse,'Edith') FROM Employee

这将保证您在行集中获得两列,即使两者中的所有值都为null。你会看到一堆'Archie'和'Edith'的价值观。如果您不使用nvl(),则可能只能获得一列或不返回。这里的问题是您的代码可以在开发环境中正常运行,甚至可以通过QA,但是当它开始生产时,表中的 values 可能会改变结构< / em>的结果!

因此,简而言之,无论何时选择可为空的列,请务必使用nvl()。

答案 5 :(得分:1)

MySQL中没有组连接。如果你想要一个组连接聚合函数,你必须自己编写。这是我的实施:

drop type T_GROUP_CONCAT;

create or replace type GROUP_CONCAT_PARAM as object
(
  val varchar2(255),
  separator varchar2(10),
  numToConcat NUMBER,
  MAP MEMBER FUNCTION GROUP_CONCAT_PARAM_ToInt  return VARCHAR2
);

--map function needed for disctinct in select clauses
CREATE OR REPLACE TYPE BODY GROUP_CONCAT_PARAM IS
    MAP MEMBER FUNCTION GROUP_CONCAT_PARAM_ToInt return VARCHAR2 is 
      begin 
        return val; 
      end; 

end;


/

CREATE OR REPLACE TYPE T_GROUP_CONCAT 
AS OBJECT (

runningConcat VARCHAR2(5000),
runningCount NUMBER,

STATIC FUNCTION ODCIAggregateInitialize
  ( actx IN OUT T_GROUP_CONCAT
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateIterate
  ( self  IN OUT T_GROUP_CONCAT,
    val   IN       GROUP_CONCAT_PARAM
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateTerminate
  ( self             IN   T_GROUP_CONCAT,
    returnValue  OUT VARCHAR2,
    flags           IN   NUMBER
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateMerge
  (self  IN OUT T_GROUP_CONCAT,
   ctx2 IN      T_GROUP_CONCAT
  ) RETURN NUMBER

);
/

CREATE OR REPLACE TYPE BODY T_GROUP_CONCAT AS

STATIC FUNCTION ODCIAggregateInitialize
  ( actx IN OUT T_GROUP_CONCAT
  ) RETURN NUMBER IS 
  BEGIN
    IF actx IS NULL THEN
      actx := T_GROUP_CONCAT ('', 0);
    ELSE
      actx.runningConcat := '';
      actx.runningCount := 0;
    END IF;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateIterate
  ( self  IN OUT T_GROUP_CONCAT,
    val   IN     GROUP_CONCAT_PARAM
  ) RETURN NUMBER IS
  BEGIN
    if self.runningCount = 0 then
        self.runningConcat := val.val;
    elsif self.runningCount < val.numToConcat then
        self.runningConcat := self.runningConcat || val.separator || val.val;
    end if;
    self.runningCount := self.runningCount + 1;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateTerminate
  ( self        IN  T_GROUP_CONCAT,
    ReturnValue OUT VARCHAR2,
    flags       IN  NUMBER
  ) RETURN NUMBER IS
  BEGIN
    returnValue := self.runningConcat;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateMerge
  (self IN OUT T_GROUP_CONCAT,
   ctx2 IN     T_GROUP_CONCAT
  ) RETURN NUMBER IS
  BEGIN
    self.runningConcat := self.runningConcat || ',' || ctx2.runningConcat;
    self.runningCount := self.runningCount + ctx2.runningCount;
    RETURN ODCIConst.Success;
  END;

END;
/

CREATE OR REPLACE FUNCTION GROUP_CONCAT
( x GROUP_CONCAT_PARAM
) RETURN VARCHAR2
--PARALLEL_ENABLE
AGGREGATE USING T_GROUP_CONCAT;
/

使用它:

select GROUP_CONCAT(GROUP_CONCAT_PARAM(tbl.someColumn, '|', 2)) from someTable tbl

答案 6 :(得分:1)

答案 7 :(得分:1)

临时表

您可以像普通表一样创建和索引它们,但每个会话/事务只能看到自己的数据。这与MS SQL不同。

全局变量

他们通过引用传递。这意味着如果将全局变量作为参数传递给过程并修改过程中的全局变量,则参数值也将更改。不过,这不是一个非常流行的方法。

<强>触发器

在最近的版本之前,无法确定类似触发器将触发的方式。如果你真的关心哪一个“在每次行更新之前”是第一次将它全部放在一个触发器中。