Weblogic JDBC Connections: multi-statement init SQL - jdbc

When setting up a data source in WLS we can give it an init SQL statement, which is executed immediately after creation of every connection for this data source.
So far we are using..
SQL ALTER SESSION SET current_schema=user01
.. as we are logging in using an application user02 which has less rights than the owner user01, but we still want the data source to see the schema.
Now we'd like to add some session meta information to the DS connections, for debugging purposes on the DB side. The statements..
DBMS_APPLICATION_INFO.set_client_info('bar');
DBMS_APPLICATION_INFO.set_module('qux', 'garp');
.. allow you to set custom strings as identifiers, which will then show up in colums of V_$SESSION, thus giving the DBA some more information about a DB connection.
My problem
How is it possible to have multi-line init SQL statements? Note that the init SQL syntax expects an SQL command which is preceded by SQL and which does not end in a semicolon ;.
Edit:
What I tried so far is something along the lines of..
begin
execute immediate 'ALTER SESSION SET current_schema=uzms01';
DBMS_APPLICATION_INFO.set_client_info('bar');
DBMS_APPLICATION_INFO.set_module('qux', 'garp');
end;
.. but I keep getting errors. :(

Looks like there was a small syntax irregularity which I did not spot because SQL developer executes it without problems...
The following snippet works (note the parentheses after immediate):
SQL BEGIN
execute immediate('alter session set current_schema=user01');
DBMS_APPLICATION_INFO.set_client_info('my client');
DBMS_APPLICATION_INFO.set_module('my module', 'my action');
END;

Related

Jmeter with Oracle 12c: the ";" is unusable

I have a jMeter 3.0 to oracle 12 c using thin connection (used ojdbc 7 and 7_c) and I cannot use the row end line ( ; ). It always returns
Cannot create PoolableConnectionFactory (ORA-00933: SQL command not properly ended
If I remove the ";" from the query everything goes fine. How can I fix this?
I found a workaround for this that avoids having the semi-colon problem:
JDBC Request Query Type needs to be: Update Statement
The query needs to be processed as a block
BEGIN
SQL Statement
END;
There are specific SQL structures that can't be executed as a block but still this enables having legit SQL code within the request and enhances having several statements in the same request.
If you are using JDBC_Request Sampler, you should NOT keep semi-colon as a trailing at the end of a line for SQL query,
Do not enter a trailing semi-colon.
so, without semi-colon, it should work properly and no need to include that.
Reference:
http://jmeter.apache.org/usermanual/component_reference.html#JDBC_Request

How query from another database that is in another machine/server

I've been looking for answer to this but I can't seem to find the right answer online and my problem goes like this.
I'm trying to query a set of records from another table which is in an another database installed in a different machine. To make it clearer:
My stored procedure is running on IP: 192.168.XX.X1. I get to retrieve all the information I need in this server but I have another set of information or records that can only be retrieved from IP: 192.168.XX.X2.
I was thinking to achieve something like:
DECLARE
-- given that both queries will only return 1 record
CURSOR IS curSample1
SELECT * FROM Database1.Table1;
colSample curSample1%ROWTYPE;
CURSOR IS curSample2
SELECT * FROM Database2.Table1;
colSample curSample2%ROWTYPE;
vText1 VARCHAR(20);
vText2 VARCHAR(20);
BEGIN
OPEN curSample1;
LOOP
FETCH curSample1 INTO colSample1;
EXIT WHEN curSample1%NOTFOUND;
vText1 := colSample1.Column1;
END LOOP;
CLOSE curSample1;
OPEN curSample2;
LOOP
FETCH curSample2 INTO colSample2;
EXIT WHEN curSample2%NOTFOUND;
vText2 := colSample2.Column2;
END LOOP;
CLOSE curSample2;
dbms_output.put_line(vText1 || ',' || vText2);
END;
Any help you could provide will be much appreciated. Thank you very much.
Note: I'm trying this approach as this is the only way we could possibly do it as of now. Thanks again.
You will have to create a db link between your database 1 and database 2. For creating a database link it is not required to have both databases on the same server. Since in your case the databases are on different server you can start with the following steps.
You need a tns entry (pointing to database 2) in the tnsnames.ora file on your database 1 server. You can check if you have this entry by connecting to SQLPLUS from your database 1 machine to database 2.
sqlplus <username>/<password>#<tnsnames of database2>
If you are able to connect from your database 1 server then you can proceed with the following steps for creating the db link.
CREATE DATABASE LINK <dblink_name> CONNECT TO <username> IDENTIFIED BY <password> USING <tnsnames of database2>
Post this you can test your database link by running the following SQL command.
select * from Table#<dblink_name>;
as i know you cannot query data cross database directly.
1,maybe you can use DBlink or DataSync to let the data which in other database can be query.
2,instead of pl/sql procedure, use other development language to do cross DB process is a good idea(ex independent java program).
3,instead of pl/sql procedure, use Oracle Java Procedure to do this.

tracing all SQL queries which have executed when application fire an order

I need to collect all the SQL queries (SELECT, UPDATE, DELETE, INSERT) which have been used by the application when any order is processed through the application.
If I can get all SQL's for atleast 50 orders processed through the application then I can check that which SELECT, UPDATE, DELETE statements are frequently in use and which tables are being frequently used by the application after finding these information.
I can get to conclusion that on which table I can use partitioning as if I get the whole SQL's with the WHERE clause I can also get to know that which type of partitioning will be better for any particular table and the partitioning.
However it seems to be a hectic exercise as there could be lots of SQL's which the application use but it helps me understand the application and also after this exercise i will be having a scrutiny report of my application behavior with database which can be used by the later employees.
For this till now i have used the DBMS_adivsor package which gives me some tables of my database to be partitioned and when i check the EXPLAIN PLAN of SQL which i used in the DBMS_ADVISOR then it occur to me that tables which are being full table scan in EXPLAIN PLAN the DBMS_ADVISOR told me to partition them.
The thing is that i can not partition the tables based on this information as its a application level partitioning and also my manager will be not convinced by this little information. so i have come up with the ABOVE plan:(
I need to do this to find out the tables where i can perform table partitioning and other performance tuning things like creating index's as i can get the where clause with filter so its like a database tuning and i want to do this as it will help me grow my career in database development.
Please help me out with this scenario.
Will this query give me required information !
select st.command
from V$SQLTEXT_WITH_NEWLINES st, SYS.V_$SQL s
where st.hash_value = s.hash_value
and parsing_schema_name = 'NETSERVICOS2CM'
and s.module = 'JDBC THIN CLIENT';
Tracing for non-dba USER's ----
GRANT SELECT ON SYS.V_$SESSION TO USER;
GRANT SELECT ON SYS.V_$MYSTAT TO USER;
To get the SID and SERAIL#
SELECT sid, serial# FROM SYS.V_$SESSION
WHERE SID = (SELECT DISTINCT SID FROM SYS.V_$MYSTAT);
Then on DBA user execute this --
EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION (sid=>3002, serial#=>31833,sql_trace=> true);
OR
on no-dba user i am using --
ALTER SESSION SET SQL_TRACE = TRUE;
OR
EXEC DBMS_SESSION.set_sql_trace(sql_trace => TRUE);
Trigger to trace a session for a particular user ----
CREATE OR REPLACE TRIGGER ON_MY_SCHEMA_LOGIN
AFTER LOGON ON DATABASE
WHEN ( USER = 'NETSERVICOS1CM' )
BEGIN
EXECUTE IMMEDIATE 'ALTER SESSION SET TRACEFILE_IDENTIFIER = "net1cm"';
EXECUTE IMMEDIATE 'alter session set statistics_level=ALL';
EXECUTE IMMEDIATE 'alter session set events ''10046 trace name context forever, level 12''';
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
After that to stop trace i am using
ALTER SESSION SET EVENTS '10046 trace name context off';
ALTER SYSTEM SET EVENTS '10046 trace name context off';
As suggested by Derek.
After this you may have multiple trace files to make a consolidate trace file we can use TRCSESS utility --
trcsess output=net1cm_trcsess.trc module="JDBC Thin Client" *net1cm.trc
It will create a single trace file net1cm_trcsess.trc for all trace file generated in my case (with trace file identifier net1cm).
Now we can use TKPROF utility to generate a report which is in human readable form using below command for example ---
tkprof net1cm_trcsess.trc OUTPUT=net1cm_trcsess.txt EXPLAIN=netservicos1cm/netservicos1 SYS=NO
Thanks
So here is my advise.
You can use several different traces for application context actions, such as INSERT, DELETE, UPDATE, SELECT, or even all actions.
Say you have a PL/SQL program run by an application, or have an OCI call to the database. You would have this oracle code at the module/stored proc level:
dbms_application_info.set_module(<module_name>,'execute');
before you execute the entire code. (After the BEGIN in the code).
or
dbms_application_info.set_module(<module_name>,'UPDATE');
before you do an update SQL statement.
To turn off application context, you would use (before the END;):
dbms_application_info.set_module(NULL,NULL);
Then when you execute the module or run the update statement you would like to trace in the module you would make sure you did this prior to and after the module runs
execute DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE( -
service_name => '<service_name>', -
module_name => '<module_name>', -
action_name => DBMS_MONITOR.ALL_ACTIONS, -
waits => TRUE, -
binds => TRUE);
All actions would be traced and you would know exactly where the statement ran and what action was executed.
To turn it off:
execute DBMS_MONITOR.SERV_MOD_ACT_TRACE_DISABLE( -
service_name => '<service_name>', -
module_name => '<module_name>', -
action_name => DBMS_MONITOR.ALL_ACTIONS);
To do this at the session level, you would do the following when 9 is the serial number and 100 is the Sid, for example. (check the syntax).
execute DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(9,190,TRUE);
To turn it off:
execute DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(9,190,FALSE);
At the database level, (You have to be very careful with this because it will generate a trace for the entire database and can fill up your diagnostic directory on your oracle database. Disclaimer: USE WITH CAUTION).
execute DBMS_MONITOR.DATABASE_TRACE_ENABLE(waits=>TRUE, binds=>TRUE, instance_name=>'<Instance_name>');
execute DBMS_MONITOR.DATABASE_TRACE_DISABLE(instance_name=>'<instance_name>');
You can leverage v$sqltext_with_newlines ,V$SESSION and v$session_longops. You can google with these words and see if these can be useful for your requirements.

OracleDatareader seems to execute an update statement

I am using oracle client 11.2.0
Dll version 4.112.3.0
We have a page in our application where people can give a sql statement and retreive results. basically do an oracle command.executereader
Recently one of my team members gave an update statement as a test and it actually performed an update on a record!!!!
Anyone who has encountered this?
Regards
Sid.
It is a normal (albeit a bit unsettling) behavior. ExecuteReader is expected to execute the sql command provided as CommandText and build a DbDataReader that you use to loop over the results.
If the command doesn't return any row to read is not something that the reader should prevent in any case. And so it is not expected that it checks if your command is really a SELECT statement.
Think for example if you pass a stored procedure name or if you have multiple sql batch to execute. (INSERT followed by a SELECT)
I think that the biggest problem here is the fact that you allow an arbitrary sql command typed by your users to reach the database engine. A very big hole in security. You should, at least, execute some analysis on the query text before submitting the code to the database engine.
I agree with Steve. Your reader will execute any command, and might get a bit confused if it's not a select and doesn't return a result set.
To prevent people from modifying anything, create a new user, grant select only (no update, no delete, no insert) on your tables to that user (grant select on tablename to seconduser). Then, log in as seconduser, and, create synonyms for your tables (create synonym tablename for realowner.tablename). Have your application use the seconduser when connecting to the DB. This should prevent people from "hacking" your site. If you want to be of the safe side, grant no permissions but create session to the second user to prevent him from creating tables, dropping your views and similar stuff (I'd guess your executereader won't allow DDL, but test it to make sure).

Explain Plan for Query in a Stored Procedure

I have a stored procedure that consists of a single select query used to insert into another table based on some minor math that is done to the arguments in the procedure. Can I generate the plan used for this query by referencing the procedure somehow, or do I have to copy and paste the query and create bind variables for the input parameters?
Use SQL Trace and TKPROF. For example, open SQL*Plus, and then issue the following code:-
alter session set tracefile_identifier = 'something-unique'
alter session set sql_trace = true;
alter session set events '10046 trace name context forever, level 8';
select 'right-before-my-sp' from dual;
exec your_stored_procedure
alter session set sql_trace = false;
Once this has been done, go look in your database's UDUMP directory for a TRC file with "something-unique" in the filename. Format this TRC file with TKPROF, and then open the formatted file and search for the string "right-before-my-sp". The SQL command issued by your stored procedure should be shortly after this section, and immediately under that SQL statement will be the plan for the SQL statement.
Edit: For the purposes of full disclosure, I should thank all those who gave me answers on this thread last week that helped me learn how to do this.
From what I understand, this was done on purpose. The idea is that individual queries within the procedure are considered separately by the optimizer, so EXPLAIN PLAN doesn't make sense against a stored proc, which could contain multiple queries/statements.
The current answer is NO, you can't run it against a proc, and you must run it against the individual statements themselves. Tricky when you have variables and calculations, but that's the way it is.
Many tools, such as Toad or SQL Developer, will prompt you for the bind variable values when you execute an explain plan. You would have to do so manually in SQL*Plus or other tools.
You could also turn on SQL tracing and execute the stored procedure, then retrieve the explain plan from the trace file.
Be careful that you do not just retrieve the explain plan for the SELECT statement. The presence of the INSERT clause can change the optimizer goal from first rows to all rows.

Resources