本章提要
-------------------------------
本章是概述性章节
1. 介绍了了解数据库内部结构对于开发的重要性
2. 介绍了如何才能开发好的数据库应用程序
-------------------------------

varchar2 类型定义时, 个人认为应该选择byte 类型, 即 varchar2(20), oracle 支持的最大的字符串是 varchar2(4000), 同时, 个人认为, 当你定义一个varchar2时, 首先预判这个地段大概能放多少内容, 比如20个字符,但是由于多字符集中, 比如utf8, 一个字符并不是对应一个字节, 比如有可能对应4个字节, 所以, 比如我们定义的字段有20个字, 那么, 我们需要定义80个字节以上, 比如 varchar2(100), 这样是比较保险的
1.
基本上 95% 的问题都可以通过 SQL解决, %5 PL/SQL 和 C 解决

自治事物的作用( 不推荐使用自治事物 )
    1) error-logging: 记录错误, 无论你的transaction是否提交, 都需要知道你曾经做过的内容
    2) demonstration concept: 用来演示, 比如你想演示两个独立的session 等

作为一个developer必须要基本上清楚database内部结构, 不能将database看成是一个"黑盒"
    举例: bitmap索引, 你需要了解bitmap索引是如何工作的, 否则就会出问题
    -- 01 test_autonomous_transaction&bitmap.sql

/*
* Test autonomous_transaction, simulation two session
* bitmap will lock the column, when uncommit transaction exist
*/ create table t
( test_flag varchar2(1)); create bitmap index t_idx on t(test_flag); -- uncommit
insert into t values('N'); -- antonomous_transaction
declare
pragma autonomous_transaction;
begin
insert into t values('Y');
end;
/

01 test_autonomous_transcation&bitmap

例子说明: 因为bitmap索引的特点是, 会对column增加锁, 所以正确的做法是对该列增加B*tree索引
    举例: 函数索引
    -- 02 function_index.sql

/*
* This program will test index on function,
* so when you want to use index on where condition,
* You need to use function.
*/ create table t
( id number primary key,
test_flag varchar2(1),
payload varchar2(20)
); -- if test_flag == 'N', return 'N'
create index t_idx on t(decode(test_flag, 'N', 'N')); insert into t
select r,
case
when mod(r, 2) = 0 then 'N'
else 'Y'
end,
'payload ' || r
from (select level r
from dual
connect by level <= 5);
/ select * from t; create or replace function get_first_unlocked_row
return t%rowtype
as
resource_busy exception;
pragma exception_init(resource_busy, -54);
l_rec t%rowtype;
begin
for x in (select rowid rid
from t
where decode(test_flag, 'N', 'N') = 'N') -- index function
loop
begin
select * into l_rec
from t
where rowid = x.rid and test_flag = 'N'
for update nowait;
return l_rec;
exception
when resource_busy then null;
when no_data_found then null;
end;
end loop;
return null;
end;
/ -- test function
declare
l_rec t%rowtype;
begin
l_rec := get_first_unlocked_row; dbms_output.put_line('I got row ' || l_rec.id || ', ' || l_rec.payload);
commit;
end;
/
-- result is 2. declare
l_rec t%rowtype;
cursor c
is
select *
from t
where decode(test_flag, 'N', 'N') = 'N' -- use decode function is for index
for update
skip locked;
begin
open c;
fetch c into l_rec;
if (c%found)
then
dbms_output.put_line('I got row ' || l_rec.id || ', ' || l_rec.payload);
end if;
close c;
end;
/ -- result is 2 declare
l_rec t%rowtype;
pragma autonomous_transaction;
cursor c
is
select *
from t
where decode(test_flag, 'N', 'N') = 'N' -- use decode function is for index
for update
skip locked; -- if you don't use this statement, the process will hang and wait
begin
open c;
fetch c into l_rec;
if (c%found)
then
dbms_output.put_line('I got row ' || l_rec.id || ', ' || l_rec.payload);
end if;
close c;
commit;
end;
/ -- result is 4

2.
怎样才能更好的创建application ?
1) understanding oracle architecture
2) Use a single connection in Oracle( 即多个查询使用一个connection, 这样当然节省资源)
3) Use Bind variables
    这里涉及到软解析和硬解析的概念, 另外, 如果不使用绑定变量, 有可能引起 SQL INJECTION(SQL注入),
    即用户输入了不合法数据, 使应用存在安全隐患.
    -- 03 & 04

/*
* This program will show use bind variable is very effect
*/ create table t(x int); create or replace procedure proc1
as
begin
for i in 1..10000
loop
execute immediate
'insert into t values(:x)'
using i;
end loop;
end;
/ create or replace procedure proc2
as
begin
for i in 1..10000
loop
execute immediate
'insert into t values('|| i ||')';
end loop;
end;
/ -- use runstats_pkg test to procedure
exec runstats_pkg.rs_start;
exec proc1;
exec runstats_pkg.rs_middle;
exec proc2;
exec runstats_pkg.rs_stop(10000);

03

/*
* This program will test SQL injection when you don't use bind variable.
*/ create or replace procedure inj(p_date in date)
as
l_rec all_users%rowtype;
c sys_refcursor;
l_query long;
begin
l_query := '
select *
from all_users
where created = ''' || p_date || '''';
dbms_output.put_line(l_query);
open c for l_query; for i in 1..5
loop
fetch c into l_rec;
exit when c%notfound;
dbms_output.put_line(l_rec.username || '.....');
end loop;
close c;
end;
/ -- you want to show
exec inj(sysdate); -- show the dangerous part about this inj procedure
create table user_pw
( uname varchar2(30) primary key,
pw varchar2(30)
); insert into user_pw(uname, pw)
values('TKYTE', 'TO SECRET');
COMMIT;
-- now, some user don't know user_pw table exist, simulation this table
-- +is very important.
grant execute on inj to scott; -- so now, scott connect the database, and do as below
alter session set nls_date_format = '"''union select tname, 0, null from tab--"';
exec leon.inj(sysdate);
/*
* The result is:
* -----------------------------------------
select *
from all_users
where created = ''union select tname, 0, null from tab--'
* -----------------------------------------
* we know table information, some important table.
*/
-- in this way, scott can see the table user_pw(very important table)
-- now they want to try to select this important table.
select * from leon.user_pw; -- but they can not, because they don't have privilege. alter session set nls_date_format = '"''union select tname || cname, 0, null from col--"';
exec leon.inj(sysdate);
/*
* The result is:
* -----------------------------------------
select *
from all_users
where created = ''union select tname || cname, 0, null from col--'
* -----------------------------------------
* we know the column information in some important table.
*/ -- use bind variable to pertect you.
create or replace procedure NOT_inj(p_date in date)
as
l_rec all_users%rowtype;
s sys_refcursor;
l_query long;
begin
l_query := '
select *
from all_users
where created = :x';
dbms_output.put_line(l_query);
open c for l_query using P_DATE;
for i in 1..5
loop
fetch c into l_rec;
exit when c%notfound;
dbms_output.put_line(l_rec.username || '....');
end loop;
close c;
end;
/ -- test not_inj
exec not_inj(sysdate);
/*
* The result is:
* -----------------------------------------
select *
from all_users
where created = :x
* -----------------------------------------
*/ -- so from now on, you must use bind variable. ^^

04

4) understanding concurrency control
    并发是很难控制的, 而且很容易导致我们的应用程序出现问题, 锁可以用来处理并发, 但是如果锁利用不当,
    就会给程序的可扩展和多用户操作造成阻碍, 所以, in your database is vital if you are to develop a scalable,
    correct application.
    举例: 控制并发
    -- 05 control_concurrency.sql

create table resources
( resource_name varchar2(25) primary key,
other_data varchar2(25)
); create table schedules
( resource_name varchar2(25) references resources,
start_time date,
end_time date
); -- the purpose about schedules is when someone want to modify table resources
-- he needs to check the schedules status, but if someone
-- modify the table schedules, and you select schedules, you can not find
-- the result modified.
select count(*)
from schedules
where resource_name = :resource_name
and (start_time < :new_start_time)
and (end_time > :new_end_time);
-- so the correct selectment is as below:
select * from resources where resource_name := resource_name for update;
-- for update is very important, it is lock on the row. so if someone want to
-- modify the table, you will know it.

5) implementing locking ( 使用锁, 上边已经有例子了)
6) flashback
    SCN: This SCN is Oracle’s internal clock: every time a commit occurs, this clock ticks upward (increments).
    flashback举例:
    -- 06 flashback_example.sql

variable scn number;
exec :scn := dbms_flashback.get_system_change_number;
print scn; select count(*) from emp; -- 14 rows
delete from emp;
select count(*) from emp; -- 0 rows -- use flashback, as of scn, as of timestamp
select count(*)
:scn then_scn,
dbms_flashback.get_system_change_number now_scn
from emp as of scn :scn; -- get the time point at :scn
-- the result is
/*
COUNT(*) THEN_SCN NOW_SCN
---------- ---------- ----------
14 6294536 6294537
*/
-- you can see the result is 14.
commit; -- commit the transaction
select cnt_now, cnt_then, :scn then_scn,
dbms_flashback.get_system_change_number now scn
from (select count(*) cnt_now from emp),
(select count(*) cnt_then, from emp as of scn :scn)
/
/*
CNT_NOW CNT_THEN THEN_SCN NOW_SCN
---------- ---------- ---------- ----------
14 14 6294536 6294552
*/ flashback table emp to scn :scn; -- the data return

7) Read Consistency and Non-Blocking Reads
    读一致性, 并且没有读锁.
8) Database Independence
    当需要数据库迁移时, 你要知道, 即便是相同的数据库, 比如都是 oracle, 那么它们的内部运作机制也可能不一样, 这也有可能
    给你带来一些问题, 更别提那些不同数据库之间的迁移问题, 比如: 将标准SQL转换成plsql:
    07 convert_SQL_to_PLSQL.sql

declare
l_some_varibale varchar2(25);
begin
if (some_condition)
then
l_some_variable := f(...);
end if; for x in (select * from t where x = l_some_variable)
loop
...
end loop;
-- as this statement
-- in oracle, this query return no data when l_some_variable was not set to a specific value
-- in sybase or sql server, the query would find rows where x was set to a null value. -- in oracle null can not use = to set condition, like as below:
select * from dual where null = null; -- return 0 rows selected
select * from dual where null <> null; -- return 0 rows selected
select * from dual where null is null; -- return X. -- to solve this problem
select * from t
where nvl(x, -1) = nvl(l_some_variable, -1); -- and you need to create a function index
create index t_idx on t(nvl(x, -1));

9) The impact of standards
    SQL99 is an ANSI/ISO standard for databases, 各个数据库在实现这个标准时有不同, 另外这个标准有些时候也是有问题的, 所以
    你只要专注你目前使用的数据库的标准.
10) Layered Programming (分层Programming)
    Let’s say you are programming using JDBC, 不同的数据库之间, 要使用不同的方法实现, 并且利用存储过程实现.
11) Knowing What's Out There
    不是完全了解SQL的特性
    example: inline views

-- inline views
select p.id, c1_sum1, c2_sum2
from p,
(select id, sum(q1) c1_sum1
from c1
group by id) c1,
(select id, sum(q2) c2_sum2
from c2
group by id) c2
where p.id = c1.id
and p.id = c2.id -- sub query that run another query per row
select p.id,
(select sum(q1) from c1 where c1.id = p.id) c1_sum1,
(select sum(q2) from c2 where c2.id = p.id) c2_sum2
from p
where p.name = '' -- sub factory with clause
with c1_vw as
(select id, sum(q1) c1_sum1
from c1
group by id),
c2_vw as
(select id, sum(q2) c2_sum2
from c2
group by id),
c1_c2 as
(select c1.id, c1.c1_sum1, c2.c2_sum2
from c1_vw c1, c2_vw c2
where c1.id = c2.id)
select p.id, c1_sum1, c2_sum2
from p, c1_c2
where p.id = c1_c2.id

12) sloving problems simply
    选择简单的办法来解决事情, 比如想控制某个用户只能一个session连接上来, 简单的办法是:
    09 do_job_easy_way.sql

create profile one_session limit sessions_per_user 1;

alter user scott profile one_session;

alter system set resource_limit = true;

13) How Do i make it run faster ?
    80%以上的性能问题都出现在设计实现级, 而不是数据库级. 在对数据库上运行的应用进行优化之前, 不要对数据库进行优化.

01 Developing Successful Oracle Application的更多相关文章

  1. 01 Developing Successful Oracle Applications

    varchar2 类型定义时, 个人认为应该选择byte 类型, 即 varchar2(20), oracle 支持的最大的字符串是 varchar2(4000), 同时, 个人认为, 当你定义一个v ...

  2. Discoverer 11.1.1.3.0以Oracle Application用户登录的必要配置

    客户这边要使用Discoverer来出报表, 就从OTN上下载安装了11.1.1.3.0版本的, 安装很简单, 一路Next, 使用的EBS版本是12.1.1.3, 结果发现用Oracle Appli ...

  3. Oracle Fusion Applications (11.1.8) Media Pack and Oracle Application Development Framework 11g (11.1.1.7.2) for Microsoft Windows x64 (64-bit)

    Oracle Fusion Applications (11.1.8) Media Pack for Microsoft Windows x64 (64-bit) 重新搜索   常见问题    提示  ...

  4. Oracle Application Express (APEX 4.2) 中进行ajax调用

    Oracle Application Express 4.2 (APEX 4.2)是一个快捷的web应用开发工具.在开发网页的过程中有时候会用到ajax请求. 建立ajax请求的方式: 1.建立后台的 ...

  5. Tuning 01 Overview of Oracle Performance Tuning

    永无止境的调优 service level agreements: 是一个量化的调优的指标. performance 只要满足业务OK就可以了, 没必要调的很多, 因为有得必有失, 一方面调的特别优化 ...

  6. Sharing The Application Tier File System in Oracle E-Business Suite Release 12.2

    The most current version of this document can be obtained in My Oracle Support Knowledge Document 13 ...

  7. Deploying Customizations in Oracle E-Business Suite Release 12.2

    DeployingCustomizations in Oracle E-Business Suite Release 12.2 This documentdescribes how to deploy ...

  8. Part 2: Oracle E-Business Suite on Cloud FAQ

    Running Oracle E-Business Suite on Oracle Cloud is simple, but it doesn't take too much effort to co ...

  9. Creating an API-Centric Web Application[转]

    Creating an API-Centric Web Application 转自 http://hub.tutsplus.com/tutorials/creating-an-api-centric ...

随机推荐

  1. DataGridView合并单元格(多行多列合并)

    一.点击在拖入的显示控件(TreeList)右上方的箭头,在Treelist任务中选择数据源,添加项目数据源,依次选择数据库.数据集,新建连接,浏览选择数据库(*.mdb),依次点击 下一步,选择“表 ...

  2. C语言中的指针和数组

    下面的内容节选自由我所执笔的会议记录.对于本文的不足之处,各位可以提出自己的看法. Q1:指针和数组到底是怎么一回事? A:指针和数组有本质的不同.指针就是一个内存地址,在32位系统下,一个指针永远占 ...

  3. 计算机科学基础知识(一)The Memory Hierarchy

    一.前言 最近一个问题经常萦绕在我的脑海:一个学习电子工程的机械师如何称为优秀的程序员?(注:本文作者本科学习机械设计,研究生转到电子工程系学习,毕业后却选择了系统程序员这样的职业).经过思考,我认为 ...

  4. 如何判断SCI期刊投稿难易度和审稿周期

    如何判断SCI期刊投稿难易度和审稿周期 要发SCI论文,前提当然是必须有一篇写好的英文论文,SCI都是英文的杂志,这个大家应该都懂的     首先谈谈投稿难易程度很多人似乎都一种误解,认为拒稿率高的杂 ...

  5. laravel建立一个分组控制器和分组路由

    路由 Route::group(['domain' => 'laravel.8g.com','namespace' => 'Admin'],function() { Route::get( ...

  6. spineRunTime for cocos2dx v3 中动画播完删除animation

    spineRunTime for cocos2dx v3 中删除animation,发现下面写法会崩溃:   spine::SkeletonAnimation* animationNode = spi ...

  7. rabbitmq增加vhost

    查看当前rabbitmq上的vhost列表: # rabbitmqctl list_vhosts Listing vhosts ... / vhost2 添加名为demo的vhost虚似主机: rab ...

  8. ES6新特性概览1

    本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...

  9. Rokid开发者社区skill之【历史上的今天】之简介+玩法+设计+实现+心得

    Skill简介: 来源:好奇心.探索欲.趣味性: 资源:百度百科: 方式:实时获取,自动更新: 技能玩法: 想要进入历史上的今天这个skill,则对若琪说:若琪,打开历史上的今天. 想要了解某天的历史 ...

  10. LeetCode: Permutations 解题报告

    Permutations Given a collection of numbers, return all possible permutations. For example,[1,2,3] ha ...