如果一定要是動態sql,一定要將日期型別用||拼起來,見下列寫法,紅色的是錯的,下面的才對,兩次型別轉換,但是沒有什麼必要
--要麼用繫結變數繫結date型別,要麼靜態sql,不要兩次轉換,直接拼日期前後不加單引號還會報錯。
sql> declare
2 v_date date := sysdate;
3 v_cnt number := 0;
4 v_sql varchar2(100);
5 begin
6 v_sql := 'select count(*) from user_objects where created<='||v_date;
7 dbms_output.put_line(v_sql);
8 v_sql := 'select count(*) from user_objects where created<='||chr(39)||v_date||chr(39);
9 dbms_output.put_line(v_sql);
10 execute immediate v_sql into v_cnt;
11 dbms_output.put_line(v_cnt);
-- v_sql := 'select count(*) from user_objects where created<=to_date('''||v_date||''',''dd-mon-yy'')';
-- dbms_output.put_line(v_sql);
12 end;
13 /
select count(*) from user_objects where created<=04-1月 -11
select count(*) from user_objects where created<='04-1月 -11'
pl/sql procedure successfully completed
drop table t;
create table t(p1 date)
partition by range(p1)
(partition p0 values less than ( to_date ('20110816', 'yyyymmdd')) tablespace users);
所以:1.對非ddl,應該要使用繫結變數,如果繫結變數適合的話
2.ddl,用不了繫結變數,必須to_date拼湊
declare
p1 date := to_date ('20110817', 'yyyymmdd');
begin
execute immediate 'alter session set nls_date_format=''yyyymmdd''';
for i in 1 .. 2
loop
execute immediate
'alter table t add partition p'
|| to_char (p1, 'yyyymmdd')
|| ' values less than ( to_date('''
|| p1
|| ''',''yyyymmdd'')) tablespace users';
p1 := p1 + 1;
end loop;
end;
--不用設nls_date_format,因為兩次轉換的nls_date_format一樣,直接to_date,因為自動轉換的字串沒有引號,需要補上引號
declare
p1 date := to_date ('20110817', 'yyyymmdd');
begin
for i in 1 .. 2
loop
execute immediate
'alter table t add partition p'
|| to_char (p1, 'yyyymmdd')
|| ' values less than ( to_date('''
|| p1
|| ''')) tablespace users';
p1 := p1 + 1;
end loop;
end;
--甚至可以去掉to_date,自動轉為目標型別,但是要補引號
declare
p1 date := to_date ('20110817', 'yyyymmdd');
begin
dbms_output.put_line( 'alter table t add partition p'
|| to_char (p1, 'yyyymmdd')
|| ' values less than ( '''
|| p1
|| ''') tablespace users');
end;
也可以對p使用顯示轉為字串,和上面一樣
'alter table t add partition p'
|| to_char (p1, 'yyyymmdd')
|| ' values less than ( to_date('''
|| to_char(p1,'yyyy-mm-dd')
|| ''',''yyyy-mm-dd'')) tablespace users'
再看乙個典型的拼湊日期的錯誤。
我常常看到別人不使用繫結變數,採用拼湊的方式傳入日期型別,比如:
declare
vname varchar2(10):='dd';
v_sql varchar2(4000);
vcnt number;
v_date date:=sysdate;
begin
v_sql:='select count(*) from test where birth='||v_date; --這裡要出錯
dbms_output.put_line(v_sql);
execute immediate v_sql into vcnt;
dbms_output.put_line(vcnt);
end;
這裡又出什麼錯呢?請看列印出的語句是什麼?
select count(*) from test where birth=08-5月 -10
原來在執行期,如果採用||date,那麼日期自動根據session日期設定引數轉換為字串,而字串連線不自動加引號,所以就變成上面的了,丟失了引號,自動轉換也失效,語句錯誤了,如果你非要那樣做,只能
1. 將v_date轉為字串,帶引號的,然後讓其自動轉換,如: v_sql:='select count(*) from test where birth='''||v_date||''''; 當然也可以使用to_date,如
v_sql:='select count(*) from test where birth=to_date('''||v_date||''')';
不需要nls_date_format設定,因為兩次轉換的格式一樣.
也可以顯示轉換,代替oracle自動轉換v_sql:='select count(*) from test where birth='''||to_char(v_date)||'''';
最完整的全部顯示轉換
v_sql:='select count(*) from test where birth=to_date('''||to_char(v_date,'yyyymmdd')||''',''yyyymmdd'')';
2. ddl用不了繫結變數,只能使用1的方法,對非ddl,要用繫結變數,解決這個問題,一般起到軟解析效果。
以上是典型的拼湊導致的程式難以編寫而且容易出錯的例子,如果採用繫結變數的方式,以上問題全可迎刃而解。
也說明了一點,繫結變數不光使我們的sql反覆執行的效率更高,在儲存過程的動態sql裡,繫結變數也會使我們減少錯誤的發生,更容易地進行程式設計(儲存過程的靜態sql自動繫結,達到軟解析或軟軟解析的效果,當然動態sql也可能軟或軟軟解析)
不加to_date,發生2次轉換
第1次,v_date是date型別,但是用||運算,變為字串
第2次,||兩邊加了引號,但是birth是date型別,又把字串轉為date型別
因為這兩次轉換的格式和環境都一樣的,所以可以自動轉來轉去,當然可讀性不是很好
block中用到self要特別注意記憶體洩露問題
self強引用會使引用計數器加1,如果在dismissviewcontroller時,如 self dismissviewcontrolleranimated no completion nil 不呼叫dealloc方法,需要將self 轉為弱引用 weak typeof self selfvc s...
python中處理鍊錶時特別注意引用傳遞的問題
刷題刷到劍指offer第57題 刪除鍊錶 已排序 中重複的結點 時,按照自己的思路做的,發現輸出結果時出現過以下問題 做題思路 鍊錶相當於乙個前後有關係的陣列,於是先把此題當做刪除陣列中重複的元素來思考,立馬想到可以借用python中的字典來統計每個數字出現的頻數 這樣遍歷一次的時間複雜度為o n ...
9 sql 中對日期的處理
1 查詢當天的使用量 select count count from t user where date create time select curdate 2查詢本週 select from t user where yearweek date format create time,y m d ...