45 个非常有用的 Oracle 查询语句

这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询。这些是所有 Oracle 开发者都必备的技能,所以快快收藏吧!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
******************************  日期/时间 相关查询 *****************************  
   
-- 1、获取当前月份的第一天 
select trunc (sysdate, 'month') "First day of current month"  from dual; 
   
-- 2、获取当前月份的最后一天 
select trunc (last_day (sysdate)) "Last day of current month"  from dual; 
       
-- 3、获取当前年份的第一天 
select trunc (sysdate, 'YEAR') "Year First Day" from dual; 
   
-- 4、获取当前年份的最后一天 
select add_months (trunc (sysdate, 'YEAR'), 12) - 1 "Year Last Day" from dual 
   
-- 5、获取当前月份的天数 
select cast (to_char (last_day (sysdate), 'dd') as int) number_of_days from dual; 
   
-- 6、获取当前月份剩下的天数 
select sysdate, last_day (sysdate) "Last", last_day (sysdate) - sysdate "Days left" from dual; 
    
-- 7、获取两个日期之间的天数 
  -- 方法一 
select round((months_between(to_date('2015-05-12','yyyy-mm-dd'), sysdate) * 30), 0) num_of_days  from dual; 
  -- 方法二 
select trunc(sysdate) - trunc(to_date('2015-05-9','yyyy-mm-dd')) from dual; 
   
-- 8、显示当前年份截止到上个月每个月份开始和结束的日期  
select add_months(trunc(sysdate, 'MONTH'), i) start_date, 
       trunc(last_day(add_months(sysdate, i))) end_date 
  from xmltable('for $i in 0 to xs:int(D) return $i'  
         passing xmlelement(d,floor(months_between(add_months(trunc(sysdate,'YEAR')-1,12),sysdate))) columns i integer path '.'); 
   
-- 9、获取直到目前为止今天过去的秒数(从 00:00 开始算 
select (sysdate - trunc (sysdate)) * 24 * 60 * 60 num_of_sec_since_morning from dual; 
   
-- 10、获取今天剩下的秒数(直到 23:59:59 结束) 
select (trunc (sysdate+1) - sysdate) * 24 * 60 * 60 num_of_sec_left from dual; 
   
   
   
******************************  数据字典 相关查询 *****************************  
   
-- 11、检查在当前数据库模式下是否存在指定的表 
select table_name from user_tables where table_name = 'TABLE_NAME'
   
-- 12、检查在当前表中是否存在指定的列 
select column_name as found from user_tab_cols where table_name = 'TABLE_NAME' and column_name = 'COLUMN_NAME'
   
-- 13、显示表结构  
 -- 方法一: 括号内容大写 
select dbms_metadata.get_ddl('TABLE','ACCT') from dual;   
   
 -- 方法二: 拼接方式(NO,必须大写) 
select t.table_name,t.column_name,t.data_type,t.data_length,t.nullable,t.column_id,c.comments,    
       (select case when t.column_name=m.column_name then 1 else 0 end from dual) iskey   
       from user_tab_cols t, user_col_comments c, (select m.column_name from user_constraints s, user_cons_columns m    
           where lower(m.table_name)='表名' and m.table_name=s.table_name   
             and m.constraint_name=s.constraint_name and s.constraint_type='P') m   
       where lower(t.table_name)='表名'    
             and c.table_name=t.table_name    
             and c.column_name=t.column_name    
             and t.hidden_column='NO'    
 order by t.column_id  
      
   -- 方法三。使用sql命令 
   desc 表名 
      
-- 14、获取当前模式 
  -- 这是另一个可以获得当前模式的名字的查询语句。有关sys_context的用法参数很多,详情自寻 
select sys_context ('userenv', 'current_schema') from dual; 
-- 15、修改当前模式 
  -- 这是另一个可以修改当前模式的查询语句,当你希望你的脚本可以在指定的用户下运行的时候非常有用,而且这是非常安全的一个方式 
alter session set current_schema = new_schema; 
   
   
   
******************************  数据库管理 相关查询 *****************************  
   
-- 16、返回 Oracle 数据库版本 
select * from v$version; 
   
-- 17、返回一些系统默认的信息(dba用户登录) 
select username, profile, default_tablespace, temporary_tablespace from dba_users; 
   
-- 18、显示数据库的字符设置信息 
select * from nls_database_parameters; 
   
-- 19、获取 Oracle 版本 
select value from v$system_parameter where name = 'compatible'
   
-- 20、存储区分大小写的数据,但是索引不区分大小写 
  -- 有些时候你可能想在数据库中查询一些独立的数据,可能会用 UPPER(..) = UPPER(..) 来进行不区分大小写的查询, 
  -- 所以就想让索引不区分大小写,不占用那么多的空间,这个语句恰好能解决你的需求 。 
create table tab (col1 varchar2 (10)); 
create index idx1 
   on tab (upper (col1)); 
analyze table a compute statistics
   
-- 21、调整没有添加数据文件的表空间 
 --- 另一个 DDL 查询来调整表空间大小 
alter database datafile '/work/oradata/STARTST/STAR02D.dbf' resize 2000m; 
   
-- 22、检查表空间的自动扩展开关 
  -- 方法一 
select substr (file_name, 1, 50), autoextensible from dba_data_files; 
  -- 方法二 
select tablespace_name, autoextensible from dba_data_files; 
   
-- 23、在表空间添加数据文件 
alter tablespace data01 add datafile '/work/oradata/STARTST/data01.dbf' size 1000m autoextend off
   
-- 24、增加数据文件的大小 
alter database datafile '/u01/app/Test_data_01.dbf' resize 2g; 
   
-- 25、查询数据库的实际大小、以GB为单位 
select sum (bytes) / 1024 / 1024 / 1024 as gb from dba_data_files; 
   
-- 26、查询数据库中数据占用的大小或者是数据库使用细节 
select sum (bytes) / 1024 / 1024 / 1024 as gb from dba_segments; 
   
-- 27、查询模式或者用户的大小、以 MB 为单位给出用户的空间大小 
select sum (bytes / 1024 / 1024) "size" from dba_segments where owner = '&owner'
   
-- 28、查询数据库中每个用户最后使用的 SQL 查询 
select s.username || '(' || s.sid || ')-' || s.osuser uname, 
         s.program || '-' || s.terminal || '(' || s.machine || ')' prog, 
         s.sid || '/' || s.serial# sid, 
         s.status "Status"
         p.spid, 
         sql_text sqltext 
    from v$sqltext_with_newlines t, v$session s, v$process p 
   where     t.address = s.sql_address 
         and p.addr = s.paddr(+) 
         and t.hash_value = s.sql_hash_value 
order by s.sid, t.piece; 
   
   
   
****************************** 性能 相关查询 *****************************  
   
-- 29、查询每个用户 CPU 的使用率,有助于用户理解数据库负载情况 
select ss.username, se.sid, value / 100 cpu_usage_seconds 
    from v$session ss, v$sesstat se, v$statname sn 
   where     se.statistic# = sn.statistic# 
         and name like '%CPU used by this session%' 
         and se.sid = ss.sid 
         and ss.status = 'ACTIVE' 
         and ss.username is not null 
order by value desc
   
-- 30、显示运行中的数据库长查询进展情况 
select a.sid, 
         a.serial#, 
         b.username, 
         opname operation, 
         target object, 
         trunc (elapsed_seconds, 5) "ET (s)"
         to_char (start_time, 'HH24:MI:SS') start_time, 
         round ( (sofar / totalwork) * 100, 2) "COMPLETE (%)" 
    from v$session_longops a, v$session b 
   where     a.sid = b.sid 
         and b.username not in ('SYS', 'SYSTEM'
         and totalwork > 0 
order by elapsed_seconds; 
   
-- 31、获取当前会话 ID,进程 ID,客户端 ID 等 
  -- 这个专门提供给想使用进程 ID 和 会话 ID 做些 voodoo magic 的用户。 
select b.sid, b.serial#, a.spid processid, b.process clientpid from v$process a, v$session b 
  where a.addr = b.paddr and b.audsid = userenv ('sessionid'); 
     
V$SESSION.SID AND V$SESSION.SERIAL# 是数据库进程 ID 
V$PROCESS.SPID 是数据库服务器后台进程 ID 
V$SESSION.PROCESS 是客户端 PROCESS ID, ON windows it IS : separated THE FIRST # IS THE PROCESS ID ON THE client AND 2nd one IS THE THREAD id. 
   
-- 32、查询特定的模式或者表中执行的最后一个 SQL 语句 
select created, timestamp, last_ddl_time from all_objects 
  where owner = 'MYSCHEMA' and object_type = 'TABLE' and object_name = 'EMPLOYEE_TABLE'
   
-- 33、查询每个执行读取的前十个 SQL 
select
  from select rownum, 
                 substr (a.sql_text, 1, 200) sql_text, 
                 trunc ( 
                    a.disk_reads / decode (a.executions, 0, 1, a.executions)) 
                    reads_per_execution, 
                 a.buffer_gets, 
                 a.disk_reads, 
                 a.executions, 
                 a.sorts, 
                 a.address 
            from v$sqlarea a 
        order by 3 desc
 where rownum < 10; 
   
-- 34、在视图中查询并显示实际的 Oracle 连接 
select osuser, username, machine,  program from v$session order by osuser; 
   
-- 35、查询并显示通过打开连接程序打开连接的组 
select program application, count (program) numero_sesiones from v$session  
    group by program  
    order by numero_sesiones desc
   
-- 36、查询并显示连接 Oracle 的用户和用户的会话数量 
select username usuario_oracle, count (username) numero_sesiones from v$session 
    group by username  
    order by numero_sesiones desc
   
-- 37、获取拥有者的对象数量 
select owner, count (owner) number_of_objects  from dba_objects 
    group by owner  
    order by number_of_objects desc
   
   
   
****************************** 实用/数学 相关的查询 *****************************  
   
-- 38、把数值转换成文字 
  -- 更多信息查看:http://viralpatel.net/blogs/convert-number-into-words-oracle-sql-query/ 
select to_char (to_date (1526, 'j'), 'jsp') from dual;  -- 输出:one thousand five hundred twenty-six 
   
-- 39、在包的源代码中查询字符串 
  -- 这个查询语句会在所有包的源代码上搜索‘FOO_SOMETHING’ ,可以帮助用户在源代码中查找特定的存储过程或者是函数调用 
select * from dba_source where upper (text) like '%FOO_SOMETHING%' and owner = 'USER_NAME'
   
-- 40、把用逗号分隔的数据插入的表中 
  -- 当你想把用逗号分隔开的字符串插入表中的时候,你可以使用其他的查询语句,比如 IN 或者是 NOT IN 。 
  -- 这里我们把‘AA,BB,CC,DD,EE,FF’转换成包含 AA,BB,CC 等作为一行的表,这样你就很容易把这些字符串插入到其他表中,并快速的做一些相关的操作。 
with csv 
     as (select 'AA,BB,CC,DD,EE,FF' as csvdata from dual) 
    select regexp_substr (csv.csvdata, '[^,]+', 1, level) pivot_char 
      from dual, csv 
connect by regexp_substr (csv.csvdata,'[^,]+', 1, level) is not null
   
-- 41、查询表中的最后一条数据记录 
  -- 方法一 
select * from dept where rowid in (select max (rowid) from 表名);  
  -- 方法二 
select * from dept  
minus 
select * from dept where rownum < (select count (*) from 表名); 
   
-- 42、在 Oracle 中做行数据乘法 
with tbl 
     as (select -2 num from dual 
         union 
         select -3 num from dual 
         union 
         select -4 num from dual), 
     sign_val 
     as (select case mod (count (*), 2) when 0 then 1 else -1 end val 
           from tbl 
          where num < 0) 
  select exp (sum (ln (abs (num)))) * val 
    from tbl, sign_val 
group by val; 
   
-- 43、在 oracle 生成随机数据 
  -- 每个开发者都想能轻松生成一堆随机数据来测试数据库多好,下面这条查询语句就可以满足你,它可以在 oracle 中生成随机的数据插入到表中 
  -- http://viralpatel.net/blogs/generating-random-data-in-oracle/ 
select level empl_id, 
           mod (rownum, 50000) dept_id, 
           trunc (dbms_random.value (1000, 500000), 2) salary, 
           decode (round (dbms_random.value (1, 2)),  1, 'M',  2, 'F') gender, 
           to_date ( 
                 round (dbms_random.value (1, 28)) 
              || '-' 
              || round (dbms_random.value (1, 12)) 
              || '-' 
              || round (dbms_random.value (1900, 2010)), 
              'DD-MM-YYYY'
              dob, 
           dbms_random.string ('x', dbms_random.value (20, 50)) address 
      from dual 
connect by level < 10000; 
   
-- 44、在 oracle 中生成随机数值 
  -- 这是 oracle 普通的旧的随机数值生成器。这个可以生成 0-100 之间的随机数值,如果你想自己设置数值范围,那么改变乘数就可以了。 
 --generate random number between 0 and 100 
select round (dbms_random.value () * 100) + 1 as random_num from dual; 
   
-- 45、检查表中是否含有任何的数据 
  -- 这个可以有很多中写法,你可以使用 count(*) 来查看表里的行的数量,但是这个查询语句比较高效和快速,而且我们只是想知道表里是否有任何的数据。 
  select 1 from 表名 where rownum = 1;

编程技巧