pass parameters to view(参数视图)
參考網址:http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:1448404423206
參數視圖:在實際的業務中,我們可能要進行權限控制,例如:某個部門經理只能看到屬于自己管理部門下的員工信息,而不能看到不屬于自己管理的部門下的員工的信息,對于系統來說,就要動態的根據當前的登錄人所屬的部門,進行動態的過濾某些數據,這時候,可以考慮使用參數視圖,但是也可以利用一個包的get/set方法進行權限的過濾
例如,以下是一個簡單的實例:
使用的包:
CREATE OR REPLACE PACKAGE get_dept_info IS-- Private variable declarationsv_dept_no NUMBER;--setter:procedurePROCEDURE set_dept_no_p(i_dept_no NUMBER);--setter:functionFUNCTION set_dept_no_f(i_dept_no NUMBER) RETURN VARCHAR2;--getterFUNCTION get_dept_no RETURN NUMBER;END get_dept_info; / CREATE OR REPLACE PACKAGE BODY get_dept_info IS--setter:procedurePROCEDURE set_dept_no_p(i_dept_no NUMBER) ISBEGINv_dept_no := i_dept_no;END;--setter:functionFUNCTION set_dept_no_f(i_dept_no NUMBER) RETURN VARCHAR2 ISBEGINv_dept_no := i_dept_no;RETURN 's';END;--getterFUNCTION get_dept_no RETURN NUMBER ISBEGINRETURN v_dept_no;END;END get_dept_info; /視圖:
1 CREATE OR REPLACE VIEW EMP_V AS 2 SELECT 3 /******************************************************************************** 4 功能描述: 5 編 寫 人: 6 修改記錄: 7 ********************************************************************************/ 8 E.EMPNO, 9 E.ENAME, 10 E.JOB, 11 E.MGR, 12 E.HIREDATE, 13 E.SAL, 14 E.COMM, 15 E.DEPTNO 16 FROM EMP E 17 WHERE e.deptno = get_dept_info.get_dept_no()--權限過濾的函數測試SQL:
1 BEGIN 2 get_dept_info.set_dept_no_p(20); 3 END; 4 SELECT * FROM emp_v t? ? ? ?注意:函數包的getter和setter方法是在一個數據庫連接中生效的(即在一個session中),所以,Oracle后臺執行的過程中,必須要一個會話中先調用setter方法,在調用getter方法,否則將不會取到任何的值。
Oracle函數和過程的區別:請參考
http://www.cnblogs.com/caroline/archive/2011/12/21/2296499.html
1、
以下內容是摘錄自ASK_TOME中的內容:
一個網友對使用參數視圖的優點進行了概括:
? ? ? I have used parameterized views recently and wanted to post my opinion on what I learnt.Following are the advantages of parameterized views. 1. The biggest advantage is that it allows you to join the view with other tables/views thus allowing you to write set based code(可以使用在結果集中使用context中設置的參數). An approach using procedure that returns a ref cursor does notallow this and I found that to be a major limitation. This of course assumes that you want to write the view with upplying the values at run time (i.e. write a parameterized view.) 2. In corner cases, it may help performance as you mentioned above (in rare cases when optimizer is not able to merge.)?可以提高性能
? ? ? Cons: 1. It is a painful thing to set the context values each time before testing(在每次測試的時候,都需要進行設置上下文的值). If your views were not parameterized you can run simple selects from the views (e.g. select * from v1) which of course parameterized views dont allowuntill you run the context setting code. (參數視圖只有在進行了設置了上下文變量的時候,才會起作用!)
? ? ? Overall, I felt that in general, one is better off not using them - use straight forward views. In case of performance issues, try the param views out. But dont start out withit in the first place if your needs are fulfilled without them (Which would be the case most of the time.),在需要的時候,使用! Thanx for a brilliant site!
2、對于復雜的潛逃的SQL語句查詢,是否可以使用參數?
? ? ?This thread has been one of the most useful links in your site... I've a doubt regarding the parameterized views
? ? 1) whether a view which is built on a set of nested queries can be parameterized or not ? ?
? ? 2) If yes then upto which level(in nested queries) can i use the parameter set using the "userenv" ? Thanks in advance
TOM給出的答案: 1) sure(可以多結果集使用遞歸參數) 2) as many as you like(沒有嵌套層級的限制) also see CREATE CONTEXT, if you have "lots to stuff in there", it'll be very useful.3、How about this alternative(使用臨時表進行替代):
? ? ?How about creating a parameter table along with?the view.?or e.g. to create a parameterized view
1 CREATE VIEW v1 AS SELECT * FROM t1 WHERE c1 = parameter.? ? First I will create a Single row table.
CREATE TABLE param_v1 (param1 VARCHAR2(40));
Then
CREATE VIEW v1 AS SELECT t1.* FROM t1, param_v1
WHERE t1.c1 = param_v1.param1;
When ever I want to query the view v1 I will first
1 DELETE FROM param_v1; -- make sure table is empty. 2 INSERT INTO param_v1 VALUES('MYVALUE'); -- insert parameter.Then
SELECT * FROM v1;
(remember that param_v1 is a single record table).
After getting the results of query I can
DELETE FROM param_v1;
Tom and all of you, please comment on this.
以下是tom給出的建議:
? ? ?well, if you are going to use a table, don't delete from it, use a global temporary table. (使用臨時表進行代替)
? ? ?but if you have just but one parameter value row per parameter name - why wouldn't you
simply use a?context?
? ?(只有一個參數,為什么不使用context ?)
4、context vs global variable
? ? consider a context like a global variable:context和全局變量的對比;
? ? We have a few complex views in our application and we want to "push" a few predicates into these views. What would you suggest be the best option for this ? Session context or global variables ??使用session中的context變量更好還是全部變量更好?
? ? Currently our plan is to declare a package with a global variable, set the predicate to this variable and get the variable in the view. Do you think context would be more useful here or makes no difference using either one ?
? TOM的回答:
? ??global variables will not work with views, so.... application context.
? ? how would you get the global variable "into the view", views cannot see plsql package variables.?
問題的補充:
? ? ?Thanks for the quick response Tom. Did not express myself clearly there. Ours is a web-app with java as the front-end talking to Oracle. So, right now, the plan is to create a package with "setters" & "getters".(使用getter和setter方法) The "setter" takes an IN parameter & assigns this IN value to the package's global variable. We set the value to this "setter" in java using prepared statement. Next step would be to call the view using prepared statement which calls the "getter" inside it. The "getter" returns this global variable. Hope I am making sense here. Thanks again for your help.
? ? TOM的回答:
? ? do not call plsql from sql unless you have to.
? ? 不要在SQL語句中調用PL/SQL除非比必須這么做
? ? your setter - should call the set context api.
? ? setter方法應該調用set context的API
? ? your getter - is just sys_context
? ? getter方法應該使用sys_context的API
? ? do not call plsql unless you have to and you very much do not have to here.?
? ? 盡量不要調用PL/SQL除非你必須這么做。
5、JDBC Connection Pooling and DBMS_SESSION
Hi Tom,Talking about the DBMS_SESSION.SET_CONTEXT I have a problem with this when working with JDBC Connection pools. 1. I have a view that reads from SYS_CONTEXTcreate or replace view TableSummaryView as select a.*, row_number() over (partition by a.VProduct_VName,a.PriceListType_VName,a.PriceGroup_VName,a.VSalesOrg_VName,a.VChannel_VName,a.VPricingCurrency_VISOCode,a.PriceRecordPriceListType_VName,a.AttributesKey order by a.vvalidity_from, a.created desc) ViewRN from Table a where ParentVID in ( select * from THE (select cast(in_list(sys_context('params','epsrlist')) as mytableType) from dual));2. But before that I set it from Java layer by calling a stored procedure which calls the DBMS_SESSION.SET_CONTEXT. Connection connection = JDBCHelper.getConnection();CallableStatement stmt = null;try {stmt = connection.prepareCall("{call setepsrlist.epsrlist(?)}");stmt.setString(1, epsrList);stmt.executeUpdate();}create package setepsrlist isprocedure epsrlist(epsrstring in varchar2); end setepsrlist; /create package body setepsrlist isprocedure epsrlist(epsrstring in varchar2) isbegindbms_session.set_context(namespace => 'params', attribute => 'epsrlist', value => epsrstring);end epsrlist; end setepsrlist; /3. When I execute the query on the View which happens on another Connection and it does not see the value that I have set on the session, since this Connection can potentially be pointing a new Database Session.(在一個新的鏈接中,進行數據的查詢)?TOM的回答:
? ?but, I'm confused...
? ? why would you think a context value set in Oracle session 1 would be or should be visible
in?Oracle session 2? (你為什么認為在session1中的上下文變量可以在或者應該在session2中課件呢????)
What I meant is a) Get a connection,獲取連接 b) Set the context,設置變量 c) Get a connection(this can be a totally different connection),獲取另一個鏈接 d) get the value from the context and it will not be there.將無法獲取到變量的值 So how can we be sure that an operation that involves multiple database JDBC connections see the value that is set.
那我們該如何在JDBC環境下查詢他的設置的值呢。
TOM的回答
grab set
grab YET ANOTHER
then try to use
why do java programmers do things like that - to generate a page, you should just
應該采用如下的方式進行:
a) grab
b) generate page
c) release
why grab/ungrab over and over and over (this happens all of the time, just to make things *really* hard and confusing) ?
6、Calling Different Views within a View based on Condition ?
? 在不同的條件下:查詢不同的表
Hi Tom, Is it possible to call two different views from within a single view based on the condition set by context ? E.g I want to create something like : Create or replace my_view as when TO_DATE(SYS_CONTEXT('userenv','client_info')) = busines_date then select * from current_view wehn TO_DATE(SYS_CONTEXT('userenv','client_info')) <> business_date then select * from Historical_view Here the current_view and historical_view has same column structure. Is there a way wherein we can achieve this ? Thanks in advance , Ram. 針對該問題,網友共提供了三種方法:1、 1 WITH current10 AS 2 (SELECT LEVEL AS lvl FROM dual CONNECT BY LEVEL < 11), 3 historical20 AS 4 (SELECT LEVEL AS lvl FROM dual CONNECT BY LEVEL < 21) 5 SELECT COUNT(*) 6 FROM (SELECT * 7 FROM current10 8 WHERE rownum = CASE 9 WHEN sys_context('userenv', 'client_info') = '10' OR 10 sys_context('userenv', 'client_info') IS NULL THEN 11 rownum 12 ELSE 13 0 14 END 15 UNION ALL 16 SELECT * 17 FROM historical20 18 WHERE rownum = CASE 19 WHEN sys_context('userenv', 'client_info') = '20' OR 20 sys_context('userenv', 'client_info') IS NULL THEN 21 rownum 22 ELSE 23 0 24 END)
2、TOM提供的方法:
1 select * from t1 where (nvl(sys_context(...),'10') = '10') 2 union all 3 select * from t2 where (nvl(sys_context(...),'20') = '20')? ? you'll find that a tad more efficient as well as the where clause could be used to actually prevent us from having to scan t1 or t2 - whereas that case could not
3、網友提供的另一種解決方法:
1 WITH current10 AS 2 (SELECT LEVEL AS lvl FROM dual CONNECT BY LEVEL < 11), 3 historical20 AS 4 (SELECT LEVEL AS lvl FROM dual CONNECT BY LEVEL < 21) 5 SELECT COUNT(*) 6 FROM (SELECT * 7 FROM current10 8 WHERE coalesce(sys_context('userenv', 'client_info'), '10') = '10' 9 UNION ALL 10 SELECT * 11 FROM historical20 12 WHERE coalesce(sys_context('userenv', 'client_info'), '20') = '20')Tom使用了10046事件:
1 alter session set events '10046 trace name context forever, level 12';7、使用/*+ gather_plan_statistics */HINT執行計劃信息的收集
select /*+ gather_plan_statistics */ * from v;查詢執行計劃結果:
1 select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));8、parameterized view examples in your site
Hi Tom,I am looking for a view where the select query has multiple conditions.So, the paramterized view will need to be set multiple values for multiple parameters.As per this page,it should be possible through dbms_session.set_context and reference later using sys_context . Can you please provide me an example ? ?TOM提供的答案:? ? ?just reference sys_context as many times as you would like.
create context foo and then set in foo the values v1, v2, v3 (or whatever) and reference
where x = sys_context( 'foo', 'v1' ) and
y = sys_context( 'foo', 'v2' ) ...?
?9、Parameterized view ?and in predicte
Hi Tom,you have mentioned the method with setting the parameter 'client_info' to parameterize a view. Your example was: create view myview as select * from t where x = userenv('client_info') / and then: SQL> exec dbms_application_info.set_client_info('my_data') SQL> select * from myview;That works very good, but what should I do, if I want to select something like that: create view myview as select * from t where x in userenv('client_info')I tried setting the parameter with something like that: exec dbms_application_info.set_client_info('(''abc'',''xyz'')'); But that doesn't work.What the best way to parameterized a range?TOM給出的答案:
http://tkyte.blogspot.com/2006/06/varying-in-lists.html
該網址可能直接無法直接訪問,需要使用代理訪問
推薦一個代理網站:
http://proxyie.cn/
?
?
?
轉載于:https://www.cnblogs.com/caroline/archive/2012/09/22/2698334.html
總結
以上是生活随笔為你收集整理的pass parameters to view(参数视图)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单页应用 (SPA)
- 下一篇: 二维码扫码就能报修单位电脑故障