显示标签为“SQL”的博文。显示所有博文
显示标签为“SQL”的博文。显示所有博文

2012年3月5日星期一

Oracle在Windows下的操作系统认证总结


一、普通用户

1. 在 windows 下创建用户 niu,或将域用户加入本地组。

2. 修改参数文件 os_authent_prefix 默认值“ops$”。

3. 修改注册表,oracle/home0 下添加 OSAUTH_PREFIX_DOMAIN 项,如果使用域,设为 true,否则设为 false;如果不是在域中,并且将其设为 true,域用机器名代替,如果不添加该项,默认值为 true。

4. 修改 SQLNET.ORA 中的 SQLNET.AUTHENTICATION_SERVICES = (NTS) 或将其注释掉,不能设为 NONE。(该项说明使用操作系统认证)

5. 连接到 Oracle,创建相应的用户:

OSAUTH_PREFIX_DOMAIN 为 TRUE 时:

Create User “OPS$DOMAIN_NAME\NIU” IDENTIFIED EXTERNALLY;
注:在使用 DOMAIN_NAME\ 时,因为有特殊符号 \,所以要用双引号包起来,此时双引号中所有字符必须用大写。

OSAUTH_PREFIX_DOMAIN为 FALSE 时:
Create User OPS$niu IDENTIFIED EXTERNALLY;
赋予给用户一些权限,如:
SQL>GRANT CONNECT TO "OPS$DOMAIN_NAME\NIU"(OPS$niu);
Grant succeeded.
SQL>
6. 以 NIU 用户登录操作操作系统
SQL> connect /
connected
SQL> show user;
USER is "<OPS$><DOMAIN_NAME>\niu"
SQL>
7. 通常情况下,数据库用户登录后,即使没有 ALTER USER 的权限,也是可以修改自己密码的,但若是以此认证方式登录数据库,则不可以(未经确认,只是尝试失败得到的结论,但仔细想想,这样要求也合理)


二、超级管理员用户

1. 与普通用户差不多,需要在创建 windows 中创建组 ora_dba(默认情况安装 oracle 的时候已经建立,ORA_<sid>_DBA 只对指明的 sid 有超级管理员权限),并将本地用户或域用户加入该组。(无需再创建 oracle 用户,相当于用 sys 登陆,os_authent_prefix 也就不起作用。)

2. 用该用户登陆 windows
连接 oracle :

SQL> connect / as sysdba
connected
SQL> show user;
USER is "sys"
SQL>


三、几个参数说明

1. 初始化文件中的 os_authent_prefix: 指明 Oracle 帐户对应 OS 帐户的前缀。

2. 注册表中的 OSAUTH_PREFIX_DOMAIN :如果不指明域(或机器名),一定要将其设为 false,通常这是造成认证失败的原因。

3. sqlnet.ora 中 sqlnet.authentication_services=(nts) 否则产生 ora-01004 错误。

4. 初始化文件中 remote_os_authent=true :该参数不一定要设,除非要用到客户端的操作系统认证(没有试验)。

5. 初始化文件中 REMOTE_LOGIN_PASSWORD :只是用于超级管理员用户,设为 NONE 则只使用操作系统认证,EXCLUSIVE 可用非共享的密码文件认证,SHARED 可用共享的密码文件认证(但只能有 sys 用户为超级管理员)。注:操作系统认证优先于密码文件认证。

四、参考:

http://www.itpub.net/showthread.php?s=&threadid=207909
http://www.itpub.net/162971,1.html
http://www.cnoug.org/viewthread.php?tid=15082
http://www.cnoug.org/viewthread.php?tid=27294&sid=DU7tZYea
http://www.cnblogs.com/zyk/archive/2004/11/09/61786.aspx

Oracle merge usage


CREATE OR REPLACE PACKAGE etl AS

    c_inserting CONSTANT PLS_INTEGER := 0;
    c_updating  CONSTANT PLS_INTEGER := 1;

    FUNCTION merge_counter (
             action_in IN PLS_INTEGER DEFAULT c_inserting
             ) RETURN PLS_INTEGER;

    FUNCTION get_merge_update_count RETURN PLS_INTEGER;

    FUNCTION get_merge_update_count (
             merge_count_in IN PLS_INTEGER
             ) RETURN PLS_INTEGER;

    FUNCTION get_merge_insert_count RETURN PLS_INTEGER;

    FUNCTION get_merge_insert_count (
             merge_count_in in PLS_INTEGER
             ) RETURN PLS_INTEGER;

    PROCEDURE reset_counters;

 END etl;
 /

 CREATE OR REPLACE PACKAGE BODY etl AS

    g_update_counter PLS_INTEGER NOT NULL := 0;
    g_insert_counter PLS_INTEGER NOT NULL := 0;

 /*-------------- START OF FUNCTION merge_counter --------------------*/
 FUNCTION merge_counter (
          action_in IN PLS_INTEGER DEFAULT c_inserting
          ) RETURN PLS_INTEGER IS
 BEGIN
    CASE action_in
       WHEN c_updating
          THEN g_update_counter := g_update_counter + 1;
       WHEN c_inserting
          THEN g_insert_counter := g_insert_counter + 1;
       ELSE
          RAISE PROGRAM_ERROR;
    END CASE;
    RETURN 0;
 END merge_counter;

 /*----------- START OF FUNCTION get_merge_update_count V1 ---------------*/
 FUNCTION get_merge_update_count
    RETURN PLS_INTEGER is
 BEGIN
    RETURN g_update_counter;
 END get_merge_update_count;

 /*----------- START OF FUNCTION get_merge_update_count V2 ---------------*/
 FUNCTION get_merge_update_count (
          merge_count_in IN PLS_INTEGER
          ) RETURN PLS_INTEGER IS
 BEGIN
    RETURN NVL( merge_count_in - g_insert_counter, 0 );
 END get_merge_update_count;

 /*----------- START OF FUNCTION get_merge_insert_count V1 ---------------*/
 FUNCTION get_merge_insert_count
    RETURN PLS_INTEGER IS
 BEGIN
    RETURN g_insert_counter;
 END get_merge_insert_count;

 /*----------- START OF FUNCTION get_merge_insert_count V2 ---------------*/
 FUNCTION get_merge_insert_count (
          merge_count_in IN PLS_INTEGER
          ) RETURN PLS_INTEGER IS
 BEGIN
    RETURN NVL( merge_count_in - g_update_counter, 0 );
 END get_merge_insert_count;

 /*-------------- START OF FUNCTION reset_counters --------------------*/
 PROCEDURE reset_counters IS
 BEGIN
    g_update_counter := 0;
    g_insert_counter := 0;
 END reset_counters;

 END etl;
 /






2. 创建一个验证的sql文件:run_mrg.sql
SQL code
set serverout on
set echo on
set pagesize 100
--
-- Run merge...
--
begin


   etl.reset_counters;


   merge into target tgt
      using source src
      on (src.id = tgt.id)
   when matched then
      update
      set value = (case etl.merge_counter(etl.c_updating)
                        when 0
                       then src.value
                    end)
    when not matched then
       insert
          ( tgt.id
          , tgt.value )
       values
          ( case etl.merge_counter(etl.c_inserting)
               when 0
               then src.id
            end
          , src.value );

    /* Use update count... */
    dbms_output.put_line(sql%rowcount || ' rows merged.');
    dbms_output.put_line(etl.get_merge_update_count || ' rows updated.');
    dbms_output.put_line(etl.get_merge_insert_count(sql%rowcount) || ' rows inserted.');

    /* Use insert count... */
    dbms_output.put_line(etl.get_merge_update_count(sql%rowcount) || ' rows updated.');
    dbms_output.put_line(etl.get_merge_insert_count || ' rows inserted.');

 end;
 /






3. 验证上述用法:
create table source ( id int, value varchar2(1) );
create table target ( id int, value varchar2(1) );


insert into source select rownum, substr(object_type,1,1) from user_objects where rownum <= 15;
insert into target select * from source where rownum <= 10;
commit;


运行结果如下:
SQL> insert into source select rownum, substr(object_type,1,1) from user_objects where rownum <= 15;


已创建11行。


SQL> insert into target select * from source where rownum <= 10;


已创建10行。


SQL> commit;


提交完成。
SQL> @E:\MyDocument\notes\oracle_run_merge.sql
SQL> set serverout on
SQL> set echo on
SQL> set pagesize 100
SQL> --
SQL> -- Run merge...
SQL> --
SQL> begin
  2
  3 etl.reset_counters;
  4
  5 merge into target tgt
  6 using source src
  7 on (src.id = tgt.id)
  8 when matched then
  9 update
 10 set value = (case etl.merge_counter(etl.c_updating)
 11 when 0
 12 then src.value
 13 end)
 14 when not matched then
 15 insert
 16 ( tgt.id
 17 , tgt.value )
 18 values
 19 ( case etl.merge_counter(etl.c_inserting)
 20 when 0
 21 then src.id
 22 end
 23 , src.value );
 24
 25 /* Use update count... */
 26 dbms_output.put_line(sql%rowcount || ' rows merged.');
 27 dbms_output.put_line(etl.get_merge_update_count || ' rows updated.');
 28 dbms_output.put_line(etl.get_merge_insert_count(sql%rowcount) || ' rows inserted.');
 29
 30 /* Use insert count... */
 31 dbms_output.put_line(etl.get_merge_update_count(sql%rowcount) || ' rows updated.');
 32 dbms_output.put_line(etl.get_merge_insert_count || ' rows inserted.');
 33
 34 end;
 35 /
22 rows merged.
20 rows updated.
2 rows inserted.
20 rows updated.
2 rows inserted.


PL/SQL 过程已成功完成。


SQL>


上述过程我是从asktom上整理出来的。希望对你有所帮助。
merge本身是不带有updated和inserted的详细信息的。




MySQL分组排名查询

--按某一字段分组取最大(小)值所在行的数据
/*
数据如下:
name val memo
a    2   a2(a的第二个值)
a    1   a1--a的第一个值
a    3   a3:a的第三个值
b    1   b1--b的第一个值
b    3   b3:b的第三个值
b    2   b2b2b2b2
b    4   b4b4
b    5   b5b5b5b5b5
*/
--创建表并插入数据:
create table tb(name varchar(10),val int,memo varchar(20))
insert into tb values('a',    2,   'a2(a的第二个值)')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('b',    1,   'b1--b的第一个值')
insert into tb values('b',    3,   'b3:b的第三个值')
insert into tb values('b',    2,   'b2b2b2b2')
insert into tb values('b',    4,   'b4b4')
insert into tb values('b',    5,   'b5b5b5b5b5')
go
--一、按name分组取val最大的值所在行的数据。
--方法1:
select a.* from tb a where val = (select max(val) from tb where name = a.name) order by a.name
--方法2:
select a.* from tb a where not exists(select 1 from tb where name = a.name and val > a.val)
--方法3:
select a.* from tb a,(select name,max(val) val from tb group by name) b where a.name = b.name and a.val = b.val order by a.name
--方法4:
select a.* from tb a inner join (select name , max(val) val from tb group by name) b on a.name = b.name and a.val = b.val order by a.name
--方法5
select a.* from tb a where 1 > (select count(*) from tb where name = a.name and val > a.val ) order by a.name
/*
name       val         memo              
---------- ----------- --------------------
a          3           a3:a的第三个值
b          5           b5b5b5b5b5
*/
--二、按name分组取val最小的值所在行的数据。
--方法1:
select a.* from tb a where val = (select min(val) from tb where name = a.name) order by a.name
--方法2:
select a.* from tb a where not exists(select 1 from tb where name = a.name and val < a.val)
--方法3:
select a.* from tb a,(select name,min(val) val from tb group by name) b where a.name = b.name and a.val = b.val order by a.name
--方法4:
select a.* from tb a inner join (select name , min(val) val from tb group by name) b on a.name = b.name and a.val = b.val order by a.name
--方法5
select a.* from tb a where 1 > (select count(*) from tb where name = a.name and val < a.val) order by a.name
/*
name       val         memo              
---------- ----------- --------------------
a          1           a1--a的第一个值
b          1           b1--b的第一个值
*/
--三、按name分组取第一次出现的行所在的数据。
select a.* from tb a where val = (select top 1 val from tb where name = a.name) order by a.name
/*
name       val         memo              
---------- ----------- --------------------
a          2           a2(a的第二个值)
b          1           b1--b的第一个值
*/
--四、按name分组随机取一条数据。
select a.* from tb a where val = (select top 1 val from tb where name = a.name order by newid()) order by a.name
/*
name       val         memo              
---------- ----------- --------------------
a          1           a1--a的第一个值
b          5           b5b5b5b5b5
*/
--五、按name分组取最小的两个(N个)val
select a.* from tb a where 2 > (select count(*) from tb where name = a.name and val < a.val ) order by a.name,a.val
select a.* from tb a where val in (select top 2 val from tb where name=a.name order by val) order by a.name,a.val
select a.* from tb a where exists (select count(*) from tb where name = a.name and val < a.val having Count(*) < 2) order by a.name
/*
name       val         memo              
---------- ----------- --------------------
a          1           a1--a的第一个值
a          2           a2(a的第二个值)
b          1           b1--b的第一个值
b          2           b2b2b2b2
*/
--六、按name分组取最大的两个(N个)val
select a.* from tb a where 2 > (select count(*) from tb where name = a.name and val > a.val ) order by a.name,a.val
select a.* from tb a where val in (select top 2 val from tb where name=a.name order by val desc) order by a.name,a.val
select a.* from tb a where exists (select count(*) from tb where name = a.name and val > a.val having Count(*) < 2) order by a.name
/*
name       val         memo              
---------- ----------- --------------------
a          2           a2(a的第二个值)
a          3           a3:a的第三个值
b          4           b4b4
b          5           b5b5b5b5b5
*/
--七,假如整行数据有重复,所有的列都相同。
/*
数据如下:
name val memo
a    2   a2(a的第二个值)
a    1   a1--a的第一个值
a    1   a1--a的第一个值
a    3   a3:a的第三个值
a    3   a3:a的第三个值
b    1   b1--b的第一个值
b    3   b3:b的第三个值
b    2   b2b2b2b2
b    4   b4b4
b    5   b5b5b5b5b5
*/
--在sql server 2000中只能用一个临时表来解决,生成一个自增列,先对val取最大或最小,然后再通过自增列来取数据。
--创建表并插入数据:
create table tb(name varchar(10),val int,memo varchar(20))
insert into tb values('a',    2,   'a2(a的第二个值)')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('b',    1,   'b1--b的第一个值')
insert into tb values('b',    3,   'b3:b的第三个值')
insert into tb values('b',    2,   'b2b2b2b2')
insert into tb values('b',    4,   'b4b4')
insert into tb values('b',    5,   'b5b5b5b5b5')
go
select * , px = identity(int,1,1) into tmp from tb
select m.name,m.val,m.memo from
(
select t.* from tmp t where val = (select min(val) from tmp where name = t.name)
) m where px = (select min(px) from
(
select t.* from tmp t where val = (select min(val) from tmp where name = t.name)
) n where n.name = m.name)
drop table tb,tmp
/*
name       val         memo
---------- ----------- --------------------
a          1           a1--a的第一个值
b          1           b1--b的第一个值
(2 行受影响)
*/
--在sql server 2005中可以使用row_number函数,不需要使用临时表。
--创建表并插入数据:
create table tb(name varchar(10),val int,memo varchar(20))
insert into tb values('a',    2,   'a2(a的第二个值)')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('b',    1,   'b1--b的第一个值')
insert into tb values('b',    3,   'b3:b的第三个值')
insert into tb values('b',    2,   'b2b2b2b2')
insert into tb values('b',    4,   'b4b4')
insert into tb values('b',    5,   'b5b5b5b5b5')
go
select m.name,m.val,m.memo from
(
select * , px = row_number() over(order by name , val) from tb
) m where px = (select min(px) from
(
select * , px = row_number() over(order by name , val) from tb
) n where n.name = m.name)
drop table tb
/*
name       val         memo
---------- ----------- --------------------
a          1           a1--a的第一个值
b          1           b1--b的第一个值
(2 行受影响)
*/

Oracle connect by 示例


SQL> create TABLE tb(ID   char(3),PID   char(3),Name  varchar(10)) ;


Table created.


SQL> INSERT  into tb SELECT   '001',NULL   ,'山东省'  from dual
  2    UNION   ALL   SELECT   '002','001','烟台市'     from dual
  3    UNION   ALL   SELECT   '004','002','招远市'     from dual
  4    UNION   ALL   SELECT   '003','001','青岛市'     from dual
  5    UNION   ALL   SELECT   '005',NULL   ,'四会市'     from dual
  6    UNION   ALL   SELECT   '006','005','清远市'     from dual
  7    UNION   ALL   SELECT   '007','006','小分市'   from dual   ;


7 rows created.




SQL> select id, pid, lpad(' ', level*2, ' ') || name newname from tb start with pid is null connect
by prior id = pid;


ID  PID
--- ---
NEWNAME
--------------------------------------------------------------------------------
001
  山东省


002 001
    烟台市


004 002
      招远市




ID  PID
--- ---
NEWNAME
--------------------------------------------------------------------------------
003 001
    青岛市


005
  四会市


006 005
    清远市




ID  PID
--- ---
NEWNAME
--------------------------------------------------------------------------------
007 006
      小分市




7 rows selected.


SQL>