2011年2月11日

关于Oracle错误:动态执行表不可访问,本会话自动统计被禁止,关闭自动统计之后的问题

用SYS登录,授权给相应的用户,用下面的语句
grant select on v_$statname to scott; 
grant select on v_$sesstat to scott; 
grant select on v_$session to scott; 
grant select on v_$mystat to scott; 

posted @ 2011-02-11 18:19 Mr.wang 阅读(889) | 评论 (0)编辑 收藏

ORA-01950: 对表空间 'USERS' 无权限

创建新的用户时,要指定default   tablespace,否则它会把system表空间当成自己的缺省表空间。这样做是不提倡的。估计原来创建某个用户的时候没有指定缺省表空间,而现在它使用系统表空间的权限被DBA给收回了。  
先用的简单的办法试试,一般缺省的ORACLE安装都是有USERS表空间的。  
比如你要在用户(或SCHEMA)usera中建表,那么你用SYSTEM登录ORACLE后,执行如下SQL  
   
ALTER   USER   usera   QUOTA   UNLIMITED   ON   USERS;  
如果没有USERS表空间,则会报错,你可以找一个其他的表空间,从v$tablespace可以看到所有的表空间。

 

下面情况sany用户开始创建的时候没有制定default tablespace   ********


SQL> connect sany/as646333
已连接。
SQL> select * from user_sys_privs
2 ;

USERNAME                       PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
SANY                           CREATE SESSION                           NO
SANY                           EXECUTE ANY PROCEDURE                    NO
SANY                           CREATE USER                              NO
SANY                           CREATE TABLE                             NO

SQL> create table bjwh(user_id number(5),user_name varchar2(20),phone varchar2(12),email varchar2(20
));
create table bjwh(user_id number(5),user_name varchar2(20),phone varchar2(12),email varchar2(20))
*
第 1 行出现错误:
ORA-01950: 对表空间 'USERS' 无权限


SQL> connect system/oracle
已连接。
SQL> alter user sany quota unlimited on users;

用户已更改。

SQL> connect sany/as646333
已连接。
SQL> create table bjwh(user_id number(5),user_name varchar2(20),phone varchar2(12),email varchar2(2
0));

表已创建。

SQL> disconnect
从 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options 断开
SQL> desc bjwh
SP2-0640: 未连接
SP2-0641: "DESCRIBE" 需要连接至服务器
SQL> connect sany/as646333
已连接。
SQL> desc bjwh
名称                                      是否为空? 类型
----------------------------------------- -------- ----------------------------
USER_ID                                            NUMBER(5)
USER_NAME                                          VARCHAR2(20)
PHONE                                              VARCHAR2(12)
EMAIL                                              VARCHAR2(20)

 

问题解决。

posted @ 2011-02-11 17:47 Mr.wang 阅读(581) | 评论 (0)编辑 收藏

oracle用户授所有权限

     摘要: 1grant alter system to linder;   2grant audit system to linder;   3  4grant create session to linder...  阅读全文

posted @ 2011-02-11 17:20 Mr.wang 阅读(625) | 评论 (0)编辑 收藏

在SQL*Pluse中以scott/tiger登录时提示ora-28000 the account is locked,解决办法

第一种:

在SQL*Pluse中以scott/tiger登录时提示ora-28000 the account is locked。

解决办法:

新装完Oracle10g后,用scott/tiger测试,会出现以下错误提示:
        oracle10g the account is locked
        oracle10g the password has expired
原因:默认Oracle10g的scott不能登陆。
解决:
(1)conn sys/sys as sysdba; //以DBA的身份登录
(2)alter user scott account unlock;// 然后解锁
(3)conn scott/tiger //弹出一个修改密码的对话框,修改一下密码就可以了

第二种:

在进行本地Net服务命名配置的时候,最后一步测试的时候,用户名和密码分别填scott和tiger.(配置方法,参考我的公用邮箱中的录像)

配置后就可以用scott和tiger登录了.

posted @ 2011-02-11 15:55 Mr.wang 阅读(721) | 评论 (0)编辑 收藏

2011年1月14日

STL源码剖析--迭代器

STL设计的精髓在于,把容器(Containers)和算法(Algorithms)分开,彼此独立设计,最后再用迭代器(Iterator)把他们粘 合在一起。可见迭代器在STL中的重要程度。迭代器已经作为一种设计思想被记录与《设计模式》中,它的意图在于“提供一种方法顺序访问一个聚合对象中的各 个元素,而又不需暴露该对象的内部表示”。

  迭代器的作用其实相当于一个智能指针,它指向容器内部的数据,可以通过operator *操作符来解指针获得数据的值,也可以通过operator ->操作符来获取数据的指针,还能够重载++,--等运算符来移动指针。

 

迭代器的分类

迭代器大致可以分为以下几种:

1、Input Interator :只允许作为输入,也就是只读(Read Only)
2、Output Interator :只允许作为输出,也就是只写(Write Only)
3、Forward Interator :允许读写,但只能做前向移动
4、Bidirectional Interator :允许读写,可以做双向移动
5、Random Access Interator :允许读写,可以任意移动

  1. struct input_iterator_tag {};
  2. struct output_iterator_tag {};
  3. struct forward_iterator_tag : public input_iterator_tag {};
  4. struct bidirectional_iterator_tag : public forward_iterator_tag {};
  5. struct random_access_iterator_tag : public bidirectional_iterator_tag {};

实现原理

下面以List为例说明迭代器的原理

  1. // List节点的定义
  2. template <class T>
  3. struct __list_node {
  4.   typedef void* void_pointer;
  5.   void_pointer next;
  6.   void_pointer prev;
  7.   T data;
  8. };
  9. // List迭代器的定义
  10. template<class T, class Ref, class Ptr>
  11. struct __list_iterator {
  12.   // 这三个typedef是为了简化后面的代码书写
  13.   typedef __list_iterator<T, T&, T*>             iterator;
  14.   typedef __list_iterator<T, const T&, const T*> const_iterator;
  15.   typedef __list_iterator<T, Ref, Ptr>           self;
  16.   typedef bidirectional_iterator_tag iterator_category;     // 迭代器类型属于bidirectional iterator
  17.   typedef T value_type;     // 值类型
  18.   typedef Ptr pointer;      // 指针类型
  19.   typedef Ref reference;    // 引用类型
  20.   typedef __list_node<T>* link_type;    // 节点指针类型
  21.   typedef size_t size_type;
  22.   typedef ptrdiff_t difference_type;
  23.   link_type node;   // 迭代器当前所指的节点
  24.   // 三种构造函数
  25.   __list_iterator(link_type x) : node(x) {}
  26.   __list_iterator() {}
  27.   __list_iterator(const iterator& x) : node(x.node) {}
  28.   // ==和!=操作符重载
  29.   bool operator==(const self& x) const { return node == x.node; }
  30.   bool operator!=(const self& x) const { return node != x.node; }
  31.   
  32.   // *操作符,汲取所指节点中的数据
  33.   reference operator*() const { return (*node).data; }
  34.   // ->操作符,汲取所指节点中数据的地址
  35.   pointer operator->() const { return &(operator*()); 
  36.   // 前置++操作符,指向下一个节点
  37.   self& operator++() { 
  38.     node = (link_type)((*node).next);
  39.     return *this;
  40.   }
  41.   // 后置++操作符,指向下一个节点
  42.   self operator++(int) { 
  43.     self tmp = *this;
  44.     ++*this;
  45.     return tmp;
  46.   }
  47.   // 前置--操作符,指向前一个节点
  48.   self& operator--() { 
  49.     node = (link_type)((*node).prev);
  50.     return *this;
  51.   }
  52.   // 后置--操作符,指向前一个节点
  53.   self operator--(int) { 
  54.     self tmp = *this;
  55.     --*this;
  56.     return tmp;
  57.   }
  58. };
  59. template <class T, class Alloc = alloc>
  60. class list {
  61.   ...
  62.   ...
  63. public:
  64.   typedef __list_iterator<T, T&, T*>             iterator;          // 注意iterator所用的就是__list_iterator
  65.   typedef __list_iterator<T, const T&, const T*> const_iterator;
  66.   ...
  67.   ...
  68. protected:
  69.   link_type node;   // 头节点,该List其实是一个带头节点的双向循环链表
  70. public:
  71.   list() { empty_initialize(); }
  72.   iterator begin() { return (link_type)((*node).next); }        // 返回头节点的下一个节点,即第一个节点的iterator
  73.   const_iterator begin() const { return (link_type)((*node).next); }
  74.   iterator end() { return node; }               // 返回头节点的iterator,其实就是返回链表的结尾
  75.   const_iterator end() const { return node; }
  76.   
  77.   ...
  78.   ...
  79. }

如果我们对List容器使用find算法,这一过程中会发生什么?
int a[] = {1,2,3,4,5};
list<int> l(a, a+5);
list<int>::iterator it = find(l.begin(), l.end(), 3);
cout << *it << end;

先看看find函数的定义

  1. template <class InputIterator, class T>
  2. InputIterator find(InputIterator first, InputIterator last, const T& value) {
  3.   while (first != last && *first != value) ++first;
  4.   return first;
  5. }

  我们所调用的find函数的特化版本其实是:
find<__list_iterator<int, int&, int*>, int>(__list_iterator<int, int&, int*> first, __list_iterator<int, int&, int*> last, const int& value)
从而find函数中所用到的!=、*、++等操作符都作用在__list_iterator<int, int&, int*>的身上,这正是泛型的作用所在。

 

STL中迭代器的各种特性

  还记得我在《STL源码剖析学习笔记2——神奇的__type_traits》中所提到的traits编程技巧么?在STL的迭代器中同样用到了这种技巧,因为STL的迭代器在使用的时候需要了解各种迭代器的特性。主要特性包含以下几种:
1、iterator_category:表示迭代器所属的类型
2、value_type:表示迭代器所指数据的类型
3、difference_type:表示两个迭代器之间的距离类型
4、pointer:表示迭代器所指数据的指针类型
5、reference:表示迭代器所指数据的引用类型

  通常迭代器的几种特性被放在iterator_traits中。

  1. // 对所有Iterator的泛化
  2. template <class Iterator>
  3. struct iterator_traits {
  4.   typedef typename Iterator::iterator_category iterator_category;
  5.   typedef typename Iterator::value_type        value_type;
  6.   typedef typename Iterator::difference_type   difference_type;
  7.   typedef typename Iterator::pointer           pointer;
  8.   typedef typename Iterator::reference         reference;
  9. };
  10. // 对指针类型的偏特化(Partial Spetialization)
  11. template <class T>
  12. struct iterator_traits<T*> {
  13.   typedef random_access_iterator_tag iterator_category;     // 指针类型是可以随机访问的
  14.   typedef T                          value_type;            // 值类型
  15.   typedef ptrdiff_t                  difference_type;       // 指针类型之间的距离一定是整型(ptrdiff_t被定义为int型)
  16.   typedef T*                         pointer;
  17.   typedef T&                         reference;
  18. };
  19. template <class T>
  20. struct iterator_traits<const T*> {      // 同上,只不过这里是常量指针
  21.   typedef random_access_iterator_tag iterator_category;
  22.   typedef T                          value_type;
  23.   typedef ptrdiff_t                  difference_type;
  24.   typedef const T*                   pointer;
  25.   typedef const T&                   reference;
  26. };

  各种不同的迭代器的特性定义如下:

  1. // input iterator的属性
  2. template <class T, class Distance> struct input_iterator {
  3.   typedef input_iterator_tag iterator_category;
  4.   typedef T                  value_type;
  5.   typedef Distance           difference_type;
  6.   typedef T*                 pointer;
  7.   typedef T&                 reference;
  8. };
  9. // output iterator的属性
  10. struct output_iterator {
  11.   typedef output_iterator_tag iterator_category;
  12.   typedef void                value_type;
  13.   typedef void                difference_type;
  14.   typedef void                pointer;
  15.   typedef void                reference;
  16. };
  17. // forward iterator的属性
  18. template <class T, class Distance> struct forward_iterator {
  19.   typedef forward_iterator_tag iterator_category;
  20.   typedef T                    value_type;
  21.   typedef Distance             difference_type;
  22.   typedef T*                   pointer;
  23.   typedef T&                   reference;
  24. };
  25. // bidirectional iterator的属性
  26. template <class T, class Distance> struct bidirectional_iterator {
  27.   typedef bidirectional_iterator_tag iterator_category;
  28.   typedef T                          value_type;
  29.   typedef Distance                   difference_type;
  30.   typedef T*                         pointer;
  31.   typedef T&                         reference;
  32. };
  33. // random access iterator的属性
  34. template <class T, class Distance> struct random_access_iterator {
  35.   typedef random_access_iterator_tag iterator_category;
  36.   typedef T                          value_type;
  37.   typedef Distance                   difference_type;
  38.   typedef T*                         pointer;
  39.   typedef T&                         reference;
  40. };

  通过iterator_traits就能得到相应interator的各种特性,这样可以让程序更灵活,也能提高效率。
下面几个例子是为了说明iterator_traits在STL中的使用
eg1. count模板函数,它的返回值必须使用difference_type

  1. template <class InputIterator, class T>
  2. typename iterator_traits<InputIterator>::difference_type
  3. count(InputIterator first, InputIterator last, const T& value) {
  4.   typename iterator_traits<InputIterator>::difference_type n = 0;   // 萃取迭代器的difference_type类型
  5.   for ( ; first != last; ++first)
  6.     if (*first == value)
  7.       ++n;
  8.   return n;
  9. }

eg2. advance模板函数,为了提高效率,必须针对不同类型的iterator重载不同的处理函数

  1. template <class InputIterator, class Distance>
  2. inline void advance(InputIterator& i, Distance n) {
  3.   __advance(i, n, iterator_category(i));    // 根据不同的类型调用不同的重载函数
  4. }
  5. // iterator_category函数的定义
  6. template <class Iterator>
  7. inline typename iterator_traits<Iterator>::iterator_category
  8. iterator_category(const Iterator&) {
  9.   typedef typename iterator_traits<Iterator>::iterator_category category;   // 其实就是返回Iterator的iterator_category类型
  10.   return category();
  11. }

  再看__advance函数针对不同迭代器的三种版本,它们分别针对input iterator、forward iterator、Bidirectional iterator和Random access iterator四种不同的迭代器

  1. // 针对input iterator和forward iterator的版本
  2. template <class InputIterator, class Distance>
  3. inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
  4.   while (n--) ++i;  // 只能单向移动
  5. }
  6. // 针对Bidirectional iterator的版本
  7. template <class BidirectionalIterator, class Distance>
  8. inline void __advance(BidirectionalIterator& i, Distance n, 
  9.                       bidirectional_iterator_tag) {
  10.   if (n >= 0)           // 根据方向不同有不同的处理
  11.     while (n--) ++i;
  12.   else
  13.     while (n++) --i;
  14. }
  15. // 针对Random access iterator的版本
  16. template <class RandomAccessIterator, class Distance>
  17. inline void __advance(RandomAccessIterator& i, Distance n, 
  18.                       random_access_iterator_tag) {
  19.   i += n;   // 随机访问,提高效率
  20. }

  总的来说,在STL中是由容器(container)来负责设计适当的迭代器(iterator),由迭代器(iterator)来负责设计适当的迭代器 属性。正因为这一点才使得容器和算法可以完全分离开来,通过迭代器提供的接口来访问容器的内部元素。在这里我们又一次看到了traits编程技巧的强大功 能,在很大程度上弥补了C++语言不是强类型语言的不足之处。


posted @ 2011-01-14 15:56 Mr.wang| 编辑 收藏

2011年1月11日

C++内联函数(转载)

C++ 内联函数和宏的区别
介绍内联函数之前,有必要介绍一下预处理宏。内联函数的功能和预处理宏的功能相似。相信大家都用过预处理宏,我们会经常定义一些宏,如
#define TABLE_COMP(x) ((x)>0?(x):0) 
  
就定义了一个宏。
    为什么要使用宏呢?因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。而宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率。 

    但是宏也有很多的不尽人意的地方。
    1、宏不能访问对象的私有成员。
    2、宏的定义很容易产生二意性。
    我们举个例子:

#define TABLE_MULTI(x) (x*x)

    我们用一个数字去调用它,TABLE_MULTI(10),这样看上去没有什么错误,结果返回100,是正确的,但是如果我们用TABLE_MULTI(10+10)去调用的话,我们期望的结果是400,而宏的调用结果是(10+10*10+10),结果是120,这显然不是我们要得到的结果。避免这些错误的方法,一是给宏的参数都加上括号。
#define TABLE_MULTI(x) ((x)*(x))

    这样可以确保不会出错,但是,即使使用了这种定义,这个宏依然有可能出错,例如使用TABLE_MULTI(a++)调用它,他们本意是希望得到(a+1)*(a+1)的结果,而实际上呢?我们可以看看宏的展开结果: (a++)*(a++),如果a的值是4,我们得到的结果是5*6=30。而我们期望的结果是5*5=25,这又出现了问题。事实上,在一些C的库函数中也有这些问题。例如: Toupper(*pChar++)就会对pChar执行两次++操作,因为Toupper实际上也是一个宏。 
    我们可以看到宏有一些难以避免的问题,怎么解决呢?

    下面就是用我要介绍的内联函数来解决这些问题,我们可以使用内联函数来取代宏的定义。而且事实上我们可以用内联函数完全取代预处理宏。
    内联函数和宏的区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。
    我们可以用Inline来定义内联函数,不过,任何在类的说明部分定义的函数都会被自动的认为是内联函数。

    下面我们来介绍一下内联函数的用法。
    内联函数必须是和函数体申明在一起,才有效。像这样的申明Inline Tablefunction(int I)是没有效果的,编译器只是把函数作为普通的函数申明,我们必须定义函数体。

Inline tablefunction(int I) {return I*I};
    这样我们才算定义了一个内联函数。我们可以把它作为一般的函数一样调用。但是执行速度确比一般函数的执行速度要快。
    我们也可以将定义在类的外部的函数定义为内联函数,比如:

Class TableClass{
 Private:
  Int I,j;
 Public: 
  Int add() ;
  Inline int dec() 
  Int GetNum();
}
inline int tableclass::GetNum(){
return I;
}

    上面申明的三个函数都是内联函数。在C++中,在类的内部定义了函数体的函数,被默认为是内联函数。而不管你是否有inline关键字。
    内联函数在C++类中,应用最广的,应该是用来定义存取函数。我们定义的类中一般会把数据成员定义成私有的或者保护的,这样,外界就不能直接读写我们类成员的数据了。对于私有或者保护成员的读写就必须使用成员接口函数来进行。如果我们把这些读写成员函数定义成内联函数的话,将会获得比较好的效率。

Class sample{
 Private:
  Int nTest;
 Public:
  Int readtest(){ return nTest;}
 Void settest(int I) {nTest=I;}
    当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。这样,内联函数就和普通函数执行效率一样了。

posted @ 2011-01-11 23:07 Mr.wang 阅读(221) | 评论 (0)编辑 收藏

仅列出标题  
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜