How to get the Oracle sql Id in the application - sql

I have a .net web service that makes some dynamically generated sql calls against ORACLE and they are performing bad in production. The DBAs keep asking for the sql ids to tune the query. They can use the OEM tool to find the slow performing query and get the sql id. But I was wondering if there is a way to know the sql id and log it so that I can retrieve it and give it to the DBAs for tuning.
Is this something that can be achieved in .net ?

Query the V$SQL dynamic view to get the SQL ID;
More on the V$SQL:
https://docs.oracle.com/cd/B19306_01/server.102/b14237/dynviews_2113.htm#REFRN30246

The following package dbms_application_info is very useful to instrument your queries.
Prior to running the processing logic from app layer, set the module/action, to identify your module.
DBMS_APPLICATION_INFO.set_module(module_name => 'add_order',
action_name => 'processing orders');
After that, set the client_info with a marker that indicates what processing is going on prior to running the sql.
Eg:
exec dbms_application_info.set_client_info('starting load from staging');
--Run the query
insert into dest_table select * from staging;
update dest_table set last_updated=sysdate;
exec dbms_application_info.set_client_info('updated the last_updated column');
delete from dest_table where order_value<0;
exec dbms_application_info.set_client_info('deleted -ve orders');
When this happens we can have a look at v$session/v$sql to see where the processing is currently taking place
SELECT sid,
serial#,
username,
osuser,
module,
action,
client_info
FROM v$session
WHERE module='add_order'
SELECT *
FROM v$sql
WHERE module='add_order'
have a look at the link
https://oracle-base.com/articles/8i/dbms_application_info

If the application can capture sufficient information to identify the session in v$session, you can query it from another session to grab the value of sql_id, or else query the v$sql_monitor view if you are licensed (requires Enterprise Edition and the Diagnostics and Tuning option). Use dbms_application_info to tag activity for better tracking.
Also you can configure database services if you haven't already, so that applications connect to a specific service rather than a generic one, and this will appear in v$session.service_name and be reported in OEM etc.
If it's practical to capture the session details from the same session immediately after the poorly-performing SQL statement completes (which it may not be, if the connection times out for example), you might try querying the prev_ details from v$session:
select s.prev_sql_id
, s.prev_child_number
, s.prev_exec_start
, s.prev_exec_id
, p.sql_text as prev_sql
, p.plan_hash_value as prev_plan
from v$session s
left join v$sql p on p.sql_id = s.prev_sql_id and p.child_number = s.prev_child_number
where s.audsid = sys_context('userenv', 'sessionid')

Related

What's the meaning of #! in Oracle DB? [duplicate]

Looking at V$SQL in my database, I have just found a strange query that looks like :
UPDATE "MYTABLE" "A1" SET "SOMECOLUMN" = (
SELECT "A2"."ANOTHERCOLUMN"
FROM "ANOTHERTABLE"#! "A2"
WHERE "A2".ROWID=:B1
)
Does anyone know the meaning of the syntax #!
I have never seen something like it before in Oracle
Thanks
It's a query that has originated on a remote database. The database where you've seen this query in V$SQL has been referenced in the query on the remote database using the #DB_NAME syntax
The remote database has pushed the query to your database for execution, but to answer the query, your database needs to pull some information back from the remote database. This is where the #! comes in, basically it's a reference back to the database where the query originated from
For example, create a test database link, even to the same database, and run this:
alter system flush shared_pool;
select sysdate from dual#myself;
select sql_text from gv$sql where sql_fulltext like '%#!%';
SQL_TEXT
--------
SELECT SYSDATE#! FROM "DUAL" "A1"
Often # in databases are related to a database link.
E.g. in Oracle I use
create public database link
mylink
connect to
remote_username
identified by
mypassword
using 'tns_service_name';
if the after this user (remote_username) has a table ANOTHERTABLE you could use:
SELECT "A2"."ANOTHERCOLUMN"
FROM "ANOTHERTABLE"#mylink "A2"
WHERE "A2".ROWID=1
How the ! sign is used here is unclear for me. Normally the ! sign is something you use to access the shell where your database client is running.
I don't know is this helped you. Good luck.

Exclamation mark in SQL (Oracle)

Looking at V$SQL in my database, I have just found a strange query that looks like :
UPDATE "MYTABLE" "A1" SET "SOMECOLUMN" = (
SELECT "A2"."ANOTHERCOLUMN"
FROM "ANOTHERTABLE"#! "A2"
WHERE "A2".ROWID=:B1
)
Does anyone know the meaning of the syntax #!
I have never seen something like it before in Oracle
Thanks
It's a query that has originated on a remote database. The database where you've seen this query in V$SQL has been referenced in the query on the remote database using the #DB_NAME syntax
The remote database has pushed the query to your database for execution, but to answer the query, your database needs to pull some information back from the remote database. This is where the #! comes in, basically it's a reference back to the database where the query originated from
For example, create a test database link, even to the same database, and run this:
alter system flush shared_pool;
select sysdate from dual#myself;
select sql_text from gv$sql where sql_fulltext like '%#!%';
SQL_TEXT
--------
SELECT SYSDATE#! FROM "DUAL" "A1"
Often # in databases are related to a database link.
E.g. in Oracle I use
create public database link
mylink
connect to
remote_username
identified by
mypassword
using 'tns_service_name';
if the after this user (remote_username) has a table ANOTHERTABLE you could use:
SELECT "A2"."ANOTHERCOLUMN"
FROM "ANOTHERTABLE"#mylink "A2"
WHERE "A2".ROWID=1
How the ! sign is used here is unclear for me. Normally the ! sign is something you use to access the shell where your database client is running.
I don't know is this helped you. Good luck.

SQL Server Update Permissions

I'm currently working with SQL Server 2008 R2, and I have only READ access to a few tables that house production data.
I'm finding that in many cases, it would be extremely nice if I could run something like the following, and get the total record count back that was affected :
USE DB
GO
BEGIN TRANSACTION
UPDATE Person
SET pType = 'retailer'
WHERE pTrackId = 20
AND pWebId LIKE 'rtlr%';
ROLLBACK TRANSACTION
However, seeing as I don't have the UPDATE permission, I cannot successfully run this script without getting :
Msg 229, Level 14, State 5, Line 5
The UPDATE permission was denied on the object 'Person', database 'DB', schema 'dbo'.
My questions :
Is there any way that my account in SQL Server can be configured so that if I want to run an UPDATE script, it would automatically be wrapped in a transaction with an rollback (so no data is actually affected)
I know I could make a copy of that data and run my script against a local SSMS instance, but I'm wondering if there is a permission-based way of accomplishing this.
I don't think there is a way to bypass SQL Server permissions. And I don't think it's a good idea to develop on production database anyway. It would be much better to have development version of the database you work with.
If the number of affected rows is all you need then you can run select instead of update.
For example:
select count(*)
from Person
where pTrackId = 20
AND pWebId LIKE 'rtlr%';
If you are only after the amount of rows that would be affected with this update, that would be same amount of rows that currently comply to the WHERE clause.
So you can just run a SELECT statement as such:
SELECT COUNT(pType)
FROM Person WHERE pTrackId = 20
AND pWebId LIKE 'rtlr%';
And you'd get the resulting potential rows affected.
1.First Login as admin in sqlserver
2.Goto login->your name->Check the roles.
3.IF u have write access,then you can accomplish the above task.
4.If not make sure you grant access to write.
If it's strictly necessary to try the update, you could write a stored procedure, accepting dynamic SQL as a string (Your UPDATE query) and wrapping the dynamic SQL in a transaction context which is then rolled back. Your account could then be granted access to that stored procedure.
Personally, I think that's a terrible idea, and incredibly unsafe - some queries break out of such transaction contexts (e.g. ALTER TABLE). You may be able to block those somehow, but it would still be a security/auditing problem.
I recommend writing a query to count the relevant rows:
SELECT COUNT(*)
FROM --tables
WHERE --your where clause
-- any other clauses here e.g. GROUP BY, HAVING ...

multiple select statements in single ODBCdataAdapter

I am trying to use an ODBCdataadapter in C# to run a query which needs to select some data into a temporary table as a preliminary step. However, this initial select statement is causing the query to terminate so that data gets put into the temp table but I can't run the second query to get it out. I have determined that the problem is the presence of two select statements in a single dataadapter query. That is to say the following code only runs the first select:
select 1
select whatever from wherever
When I run my query directly through SQL Server Management Studio it works fine. Has anyone encountered this sort of issue before? I have tried the exact same query previously on similar databases using the same C# code (only the connection string is different) and had no problems.
Before you ask, the temp table is helpful because otherwise I would be running a whole lot of inner select statements which would bog down the database.
Assuming you're executing a Command that's command type is CommandText you need a ; to separate the statements.
select 1;
select whatever from wherever;
You might also want to consider using a Stored Procedure if possible. You should also use the SQL client objects instead of the ODBC client. That way you can take advantage of additional methods that aren't available otherwise. You're supposed to get better perf as well.
If you need to support multiple Databases you can just use the DataAdapter class and use a Factory o create the concrete types. This gives you the benefits of using the native drivers without being tied to a specific backend. ORMS that support multiple back ends typically do this. The Enterprise Library Data Access Application Block while not an ORM does this as well.
Unfortunately I do not have write access to the DB as my organization has been contracted just to extract information to a data warehouse. The program is one generalized for use on multiple systems which is why we went with ODBC. I suppose it would not be terrible to rewrite it using SQL Management Objects.
ODBC Connection requires a single select statement and its retrieval from SQL Server.
If any such functionality is required, a Hack can do the purpose
use the query
SET NOCOUNT ON
at the top of your select statement.
When SET NOCOUNT is ON, the count (indicating the number of rows affected by a Transact-SQL statement) is not returned.
When SET NOCOUNT is OFF, the count is returned. It is used with any SELECT, INSERT, UPDATE, DELETE statement.
The setting of SET NOCOUNT is set at execute or run time and not at parse time.
SET NOCOUNT ON mainly improves stored procedure (SP) performance.
Syntax:
SET NOCOUNT { ON | OFF }

Why do I get an open transaction when just selecting from a database View?

If I execute a simple select statement in pl/sql developer against a database table, I get a standard set of results back as I would expect.
Recently, I pasted a query from a stored procedure that happened to select from a view, and noticed that a transaction was seemingly left open. This was appraent by the rollback and commit options were available in PL/SQL developer.
A poll of other developers revealed that this seems to affect some but not others, which lead me to suspect PL/SQL Developer settings.
Why on earth would this be the case? The view itelf has a DBLink to another database, but I wouldn't expect this to have any effect.
Any thoughts?
Contrary to your expectation, it looks like the database link is the source of the open transaction. I've noticed behaviour like this before when running SELECT queries on remote tables in PL/SQL Developer.
To quote Tom Kyte (source):
distributed stuff starts a transaction "just in case".
EDIT: 'Any SQL statement starts a transaction in Oracle'? No, it does not, and here's a demonstration of it. This demonstration uses the data dictionary view V$TRANSACTION, which lists the active transactions. This is all running on my local Oracle XE database, which has no users other than me connected to it.
We'll use the following table during this demonstration. It contains only a single column:
SQL> desc test;
Name Null? Type
----------------------------------------- -------- ----------------------------
A NUMBER(38)
SQL> select count(*) from v$transaction;
COUNT(1)
----------
0
No active transactions at the moment. Let's run a SQL query against this table:
SQL> select * from test;
A
----------
2
SQL> select count(*) from v$transaction;
COUNT(1)
----------
0
Still no active transactions. Now let's do something that will start a transaction:
SQL> insert into test values (1);
1 row created.
SQL> select count(*) from v$transaction;
COUNT(1)
----------
1
As expected, we now have an active transaction.
SQL> commit;
Commit complete.
SQL> select count(*) from v$transaction;
COUNT(1)
----------
0
After committing the transaction, it's no longer active.
Now, let's create a database link. I'm using Oracle XE, and the following creates a database link from my Oracle XE instance back to itself:
SQL> create database link loopback_xe connect to user identified by password using 'XE';
Database link created.
Now let's see what happens when we select from the table over the database link:
SQL> select count(*) from v$transaction;
COUNT(1)
----------
0
SQL> select * from test#loopback_xe;
A
----------
2
1
SQL> select count(*) from v$transaction;
COUNT(1)
----------
1
As you can see, simply selecting from a remote table opens a transaction.
I'm not sure exactly what there is to commit or rollback here, but I have to admit to not knowing the ins and outs of distributed transactions, within which the answer probably lies.
Any SQL Statement starts a transaction in Oracle.
From the manual:
A transaction begins with the first executable SQL statement. A transaction ends when it is committed or rolled back, either explicitly with a COMMIT or ROLLBACK statement or implicitly when a DDL statement is issued. [...] An executable SQL statement is a SQL statement that generates calls to an instance, including DML and DDL statements
Most probably those who are not seing this are running in auto-commit mode where the transaction started by a statement is immediately committed after the statement has finished.
Others have claimed that a SELECT is not DML, but again the manual clearly states:
Data manipulation language (DML) statements query or manipulate data in existing schema objects. They enable you to:
* Retrieve or fetch data from one or more tables or views (SELECT)
* Add new rows of data into a table or view (INSERT)
[...]
You absolutely cannot open a transaction strictly with a normal query. You may open one across a database link. The guy who posted a link to the doctors either deliberately or utterly carelessly left out the 2nd sentence.
"A transaction in Oracle Database begins when the first executable SQL
statement is encountered. An executable SQL statement is a SQL
statement that generates calls to an instance, including DML and DDL
statements."
SELECT is neither a DML nor a DDL. It is also TRIVIAL to actually test this. I don't want to come off like a troll here, but its really annoying when people just throw out answers on a forum to try to get points and the answers are complete garbage.
Read the rest of the doc and TEST IT FIRST.
login to a session
run a select
see if you have an open transaction by joining v$Session (for your session) to v$transaction.
If a record comes back, you have a transaction. If not, you don't.
Note, according to the Oracle 11g Admin Guide, if you do a plain old SELECT across a database link you will start a transaction, which needs to be committed (or rolled back).
Select is a part of DML only but lock is not acquired, A row lock is fetched upon insert/update/delete/ select for update. -Ross is right.
https://docs.oracle.com/cd/E11882_01/server.112/e41084/ap_locks001.htm#SQLRF55502
ROW Lock Table lock
SELECT ... FROM table... ----- None
INSERT INTO table ... Yes SX
Same with update delete and select for update.
TLDR : On select from remote database you also create session and connection for remote DB. That session and connection persists as long as local user session. As you can guess this can lead to some problems with keeping up with session and connections.
SO ALWAYS DO A COMMIT :
SELECT * FROM emp#sales;
COMMIT;
I like a long read section :
This was bugging me also so much why there is an transaction on selects from db_links
and decided to finally end this so from oracle documentation :
Oracle® Database Administrator's Guide
11g Release 2 (11.2)
https://docs.oracle.com/html/E25494_01/ds_appdev002.htm
Controlling Connections Established by Database Links
When a global object name is referenced in a SQL statement or remote procedure call, database links establish a connection to a session in the remote database on behalf of the local user. The remote connection and session are only created if the connection has not already been established previously for the local user session.
The connections and sessions established to remote databases persist for the duration of the local user's session, unless the application or user explicitly terminates them. Note that when you issue a SELECT statement across a database link, a transaction lock is placed on the undo segments. To rerelease the segment, you must issue a COMMIT or ROLLBACK statement.
Terminating remote connections established using database links is useful for disconnecting high cost connections that are no longer required by the application. You can terminate a remote connection and session using the ALTER SESSION statement with the CLOSE DATABASE LINK clause. For example, assume you issue the following transactions:
SELECT * FROM emp#sales;
COMMIT;
The following statement terminates the session in the remote database pointed to by the sales database link:
ALTER SESSION CLOSE DATABASE LINK sales;
To close a database link connection in your user session, you must have the ALTER SESSION system privilege.
Note:
Before closing a database link, first close all cursors that use the link and then end your current transaction if it uses the link.
See Also:
Oracle Database SQL Language Reference for more information about the ALTER SESSION statement