对于刚接触平台的人来说,Oracle有什么问题,但对于关系数据库(MySQL,MS SQL Server,Postgres等)来说并不陌生。
我正在寻找的那种事情的两个例子
许多关系数据库产品处理为您创建auto_increment密钥。 Oracle没有,您必须手动创建序列,然后创建触发器
通过SQL Developer界面插入数据时,必须手动提交数据
PHP相关陷阱的奖励积分,因为这是假设有经验的newb将使用的平台我将。
答案 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
中所示,但与MySQL
和SQL 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 Server
和MySQL
一样进行排序,请使用:
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
不同,MySQL
与InnoDB
不同。
在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不同。
全局变量
他们通过引用传递。这意味着如果将全局变量作为参数传递给过程并修改过程中的全局变量,则参数值也将更改。不过,这不是一个非常流行的方法。
<强>触发器强>
在最近的版本之前,无法确定类似触发器将触发的方式。如果你真的关心哪一个“在每次行更新之前”是第一次将它全部放在一个触发器中。