Php 甲骨文找到了一个有经验的新手
对于刚接触该平台但对关系数据库(MySQL、MS SQL Server、Postgres等)并不陌生的人来说,Oracle有哪些普遍的收获 我正在寻找的这类东西的两个例子Php 甲骨文找到了一个有经验的新手,php,mysql,sql-server,oracle,postgresql,Php,Mysql,Sql Server,Oracle,Postgresql,对于刚接触该平台但对关系数据库(MySQL、MS SQL Server、Postgres等)并不陌生的人来说,Oracle有哪些普遍的收获 我正在寻找的这类东西的两个例子 许多关系数据库产品处理为您创建自动增量键的过程。Oracle没有,您必须手动创建序列,然后创建触发器 通过SQL Developer接口插入数据时,必须手动提交数据 PHP相关gotchas的额外积分,因为这是我将这个假设的有经验的新手将使用的平台 注意:我在这里只解释了哥特加,I。EOracle行为与其他系统不同的情况Ora
Oracle
行为与其他系统不同的情况Oracle
比其他RDBMS
有许多好处,但它们不是本文的主题。
- 如果没有中的,则无法选择
如果失败,您需要:SELECT 1
SELECT 1 FROM dual
- 空字符串和
是一回事NULL
不返回任何内容SELECT * FROM dual WHERE '' = ''
- 既没有
也没有顶部
。您可以在限制
子句中限制结果:WHERE
这是一个问题SELECT * FROM ( SELECT * FROM mytable ORDER BY col ) WHERE rownum < 10
值没有索引。此查询不会使用索引进行排序: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
要在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
语句 行锁存储在数据页上locktable
- 在
中,没有“Oracle
索引”,而是“索引组织的表”。默认情况下,表是堆组织的(与聚集的
和sqlserver
以及MySQL
不同) 在Oracleworld中,“集群存储”意味着组织多个表,以便共享公共键(来自多个表)的行也共享一个数据页 一个数据页承载来自多个表的多行,这使得这个键上的连接超快速InnoDB
如果您使用分层数据,则“连接方式”非常好。与SQL Server相比,我似乎遇到了更多对架构对象和数据区分大小写的Oracle数据库。不要忘记在行集中可能完全填充空值的任何列周围使用nvl(列)。否则,该列将从行集中丢失 没错,完全失踪了 例如:
SELECT nvl(employeeName,'Archie'), nvl(employeeSpouse,'Edith') FROM Employee
这将保证在行集中有两列,即使这两列中的所有值都为null。你会看到一堆“阿尔奇”和“伊迪丝”的值。如果不使用nvl(),则可能只返回一列或两列都不返回。问题的关键在于,代码可以在开发环境中正常运行,甚至可以通过QA,但当它进入生产环境时,表中的值可能会改变结果的结构
因此,简而言之,无论何时选择可为空的列,请确保使用nvl()。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;
/
我在这里写了一些不同之处:一条评论:使用序列不必创建触发器,除非您坚持复制Sybase/SQL Server IDENTITY列的行为。我发现直接在实际的insert语句中使用序列更有用,例如
INSERT
INTO MyTable
( KeyCol
, Name
, Value
)
SELECT Seq_MyTable.NextVal
, 'some name'
, 123
FROM dual;
您不需要担心触发器执行的开销,并且可以灵活地处理向表中插入行的问题,而不必担心被分配的序列值(例如在将数据从模式移动到另一个模式时)。您还可以从序列中预先选择值,以插入数据范围,以及标识功能使其难以或不可能使用的其他技术。临时表 您可以像创建普通表一样创建和索引它们,但每个会话/事务只能看到自己的数据。这与MS SQL不同 全局变量 它们是通过引用传递的。这意味着,如果将全局变量作为参数传递给过程,并在过程中修改全局变量,则参数值也将更改。不过,这不是一种非常流行的方法 触发器
直到最近的版本,还没有办法确定类似触发器的触发方式。如果你真的关心“每行更新前”是第一个,你就把它放在一个触发器中。你不需要触发器来更新序列-你使用sequence.nextvalgod信息,可能值得一个实际的答案(与注释相反),但它确实会导致可移植性较差的SQL,这会导致一些人(对或错)改为使用触发器。另外,第2点是一个可以在SQL Developer中打开的首选项(工具->首选项->数据库->工作表参数->SQL工作表中的自动提交)。谢谢你的提示steve。你需要解释一下。AFAIK select“”在DUAL中为NULL,将为false@
SELECT nvl(employeeName,'Archie'), nvl(employeeSpouse,'Edith') FROM Employee
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
INSERT
INTO MyTable
( KeyCol
, Name
, Value
)
SELECT Seq_MyTable.NextVal
, 'some name'
, 123
FROM dual;