select statements in oracle with for read only - sql

I have a Database Links in Oracle, and when I query some data like: select * from kfilwrk#something for read only, I have an error: "missing keyword". I can just write select statement, but the problem is, I need to add for read only because my select statement may change some data.
UPD: when I write simple select statement and retrieve data, after that I close SQL Developer, it asks me to rollback or commit data. It means the select cursor updates some data

The syntax is WITH READ ONLY, not FOR READ ONLY and it can only be used with sub queries:
SQL> CREATE DATABASE LINK MyLink CONNECT TO HR IDENTIFIED BY HR USING 'sampleHost:1521/XE';
SQL> SELECT COUNT(*) FROM (SELECT * FROM Dual#MyLink WITH READ ONLY);
COUNT(*)
----------
1
See also http://docs.oracle.com/database/121/SQLRF/statements_10002.htm#SQLRF55295:
subquery_restriction_clause The subquery_restriction_clause lets you restrict the subquery in one of the following ways:
WITH READ ONLY Specify WITH READ ONLY to indicate that the table or view cannot be updated.
Alternatively, you can set your transaction into read only mode:
SET TRANSACTION READ ONLY; -- Read only
...
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- back to default (read committed)

If you query over a DB_LINK the database assumes there are transactions to COMMIT on close.
Also, SQL Developer has a shared connection for the Worksheet and the Database Navigator/Object Editors. So if you had opened a table and changed a record - that's on the same connection as your SELECT query on the worksheet.

Related

SQL injection payload after order by in SQL query

Trying to exploit SQL injection for my assignment. Is it possible to execute delete or drop query after order by in select query without using the semicolon in Postgresql?
This is my sample query:
Select *
from table
order by {sql injection payload}
Without using the semicolon in the payload, can we delete data or drop a table?
https://stackoverflow.com/a/6800585
Do we have similar to this Postgrsql?
I tried
Select * from (delete from table_name returning *) a
But getting sql error as 'syntax error at or near from'
Check this document it says we can bypass forbidden character by CHR()
https://book.hacktricks.xyz/pentesting-web/sql-injection/postgresql-injection
DELETE cannot be put inside a subquery. Nor can DELETE be part of a UNION.
So aside from running a second query (that is, separated by a semicolon), there's almost no way you can do what you describe.
You could invoke a stored procedure or function, if you knew of an existing function that performs a DELETE. Example:
Select *
from table
order by {sql injection payload}
After your payload modifies this query:
Select *
from table
order by SomeFunctionThatDeletes()
Another type which works because you can select from a procedure in PostgreSQL:
Select *
from table
order by id
UNION
Select *
from SomeProcedureThatDeletes()
You can't create the function or procedure with SQL injection, so that routine must exist already, and you would need to know its name and how to call it.
DELETE or DROP TABLE are not the only bad things that can happen from SQL injection. It could be a problem if the query returns data that the current user shouldn't have privilege to see. For example, records about a different user's purchases or medical history.
SQL injection can also be accidental instead of malicious. I would even say that most instances of SQL injection result in simple errors instead of data breaches. Those aren't really attacks, but they lead to an unsatisfactory experience for your users.

DB2 Error Code -495 while we try deleting records counts more than 400k

We have following query to get the records deleted on fk_data_table, and been found we weren’t able to, as because of 400k records.
Delete FROM BOM_LINK WHERE TEST_OBJECT_OID IN (SELECT DISTINCT
TESTOBJECT_OID FROM TESTOBJECT WHERE TESTOBJECT.TESTOBJECTTYPE_OID =
3);
DB2 Error Code -495 https://www.sqlerror.de/db2_sql_error_-495_sqlstate_57051.html
I think what we can do is,
We can write a function or procedure
We can retrieve data by writing query by SELECT and CURSOR options, instead directly deleting
While iterating CURSOR we can try deleting it. (I am not sure that in this way we can delete the row, anyway lets find this out)
We can do periodical commit, instead of doing commit after extensive amount of deletion.
Could someone help us sorting out this issue which we are facing. Pointing to some SQL code snippets will help us a lot.
Unfortunately, Db2 for Z/OS doesn't allow to delete from a subselect.
I don't have Db2 for Z/OS at hand to check, but you may try the following:
CREATE VIEW BOM_LINK_V AS
SELECT *
FROM BOM_LINK B
WHERE EXISTS
(
SELECT 1
FROM TESTOBJECT T
WHERE T.TESTOBJECT_OID = B.TEST_OBJECT_OID
AND T.TESTOBJECTTYPE_OID = 3
)
FETCH FIRST 1000 ROWS ONLY;
Run DELETE FROM BOM_LINK_V until you get SQLSTATE = '02000' (no rows affected).
Update:
The DELETE statement since v12 supports the FETCH FIRST clause.
So, you may run the following without creating a view until you get SQLSTATE = '02000':
DELETE FROM BOM_LINK B
WHERE EXISTS
(
SELECT 1
FROM TESTOBJECT T
WHERE T.TESTOBJECT_OID = B.TEST_OBJECT_OID
AND T.TESTOBJECTTYPE_OID = 3
)
FETCH FIRST 1000 ROWS ONLY;

Optimization when merging from Oracle datalink

I am trying to write an Oracle procedure to merge data from a remote datalink into a local table. Individually the pieces work quickly, but together they time out. Here is a simplified version of what I am trying.
What works:
Select distinct ProjectID from Project where LastUpdated < (sysdate - 6/24);
--Works in split second.
Merge into project
using (select /*+DRIVING_SITE(remoteCompData)*/
rp.projectID,
rp.otherdata
FROM Them.Remote_Data#DBLink rd
WHERE rd.projectID in (1,2,3)) sourceData -- hardcoded IDs
On (rd.projectID = project.projectID)
When matched...
-- Merge statement works quickly when the IDs are hard coded
What doesn't work: Combining the two statements above.
Merge into project
using (select /*+DRIVING_SITE(rd)*/ -- driving site helps when this piece is extracted from the larger statement
rp.projectID,
rp.otherdata
FROM Them.Remote_Data#DBLink rd
WHERE rd.projectID in --in statement that works quickly by itself.
(Select distinct ProjectID from Project where LastUpdated < (sysdate - 6/24))
-- This select in the in clause one returns 10 rows. Its a test database.
On (rd.projectID = project.projectID)
)
When matched...
-- When I run this statement in SQL Developer, this is all that I get without the data updating
Connecting to the database local.
Process exited.
Disconnecting from the database local.
I also tried pulling out the in statement into a with statement hoping it would execute differently, but it had no effect.
Any direction for paths to pursue would be appreciated.
Thanks.
The /*+DRIVING_SITE(rd)*/ hint doesn't work with MERGE because the operation must run in the database where the merged table sits. Which in this case is the local database. That means the whole result set from the remote table is pulled across the database link and then filtered against the data from the local table.
So, discard the hint. I also suggest you convert the IN clause into a join:
Merge into project p
using (select rp.projectID,
rp.otherdata
FROM Project ld
inner join Them.Remote_Data#DBLink rd
on rd.projectID = ld.projectID
where ld.LastUpdated < (sysdate - 6/24)) q
-- This select in the in clause one returns 10 rows. Its a test database.
On (q.projectID = p.projectID)
)
Please bear in mind that answers to performance tuning questions without sufficient detail are just guesses.
I found your question having same problem. Yes, the hint in query is ignored when the query is included into using clause of merge command.
In my case I created work table, say w_remote_data for your example, and splitted merge command into two commands: (1) fill the work table, (2) invoke merge command using work table.
The pitfall is, we cannot simply use neither of commands create w_remote_data as select /*+DRIVING_SITE(rd)*/ ... or insert into w_remote_data select /*+DRIVING_SITE(rd)*/ ... to fill the work table. Both of these commands are valid but they are slow - the hint does not apply too so we would not get rid of the problem. The solution is in PLSQL: collect result of query in using clause using intermediate collection. See example (for simplicity I assume w_remote_data has same structure as remote_data, otherwise we have to define custom record instead of %rowtype):
declare
type ct is table of w_remote_data%rowtype;
c ct;
i pls_integer;
begin
execute immediate 'truncate table w_remote_data';
select /*+DRIVING_SITE(rd)*/ *
bulk collect into c
from Them.Remote_Data#DBLink rd ...;
if c.count > 0 then
forall i in c.first..c.last
insert into w_remote_data values c(i);
end if;
merge into project p using (select * from w_remote_data) ...;
execute immediate 'truncate table w_remote_data';
end;
My case was ETL script where I could rely it won't run in parallel. Otherwise we would have to cope with temporary (session-private) tables, I didn't try if it works with them.

How to store the result of select statement into the temporary table in Oracle?

We can write select column1,column2 into #temp from tableName in SQL Server. But I am unable to write the same query in an Oracle database.
I want to store the result of select/insert/delete/update or any result set into a local temporary table in oracle database. How I can do this?
I am executing below query in my Oracle sql developer tool:
select * into #temp
from bmi;
but I am getting the error as follow please help to find this error.
when I execute the same query in Microsoft SQL Server it get executed & #temp table get created which is not present in the database but it can hold the data for that particular session. so i want same scenario in ORACLE database.
ORA-00911: invalid character
00911. 00000 - "invalid character"
*Cause: identifiers may not start with any ASCII character other than
letters and numbers. $#_ are also allowed after the first
character. Identifiers enclosed by doublequotes may contain
any character other than a doublequote. Alternative quotes
(q'#...#') cannot use spaces, tabs, or carriage returns as
delimiters. For all other contexts, consult the SQL Language
Reference Manual.
*Action:
Error at Line: 1 Column: 15
I want to store the result of select/insert/delete/update or any result set into a local temporary table in oracle database,How I can Do This?
You can't. Oracle doesn't have local temporary tables, it doesn't work like that. But it doesn't need to. Oracle has a very different internal model from SQL Server which means a lot of SQL Server practices are unnecessary in Oracle. (To be fair SQL Server has neat things which Oracle doesn't, like ANSI 92 Joins for DML.)
The key insight is: you don't want to store the result of select/insert/delete/update or any result set into a local temporary table. That is something you had to do in T-SQL to achieve the end goal of implementing some business logic. But what you actually wanted to do in SQL Server and what you want to do in Oracle is write some code which delivers value to your organisation.
So, with that mindset in place, what do you need to do?
If you want to loop round a result set then perhaps a Cursor Loop is what you're looking for?
for rec in ( select * from some_table
where the_date = date '2018-02-01' )
loop
...
If you want to work on some data prior to inserting it into a data then perhaps you should use a PL/SQL collection:
type l_recs is table of some_table%rowtype;
But maybe you just need to understand Oracle's Transaction Management model. A lot of things are possible in pure SQL without any need for procedural framework.
Create temporary table :
create global temporary table
results_temp (column1, column2)
on commit preserve rows;
and then insert to it from your table:
insert into results_temp (column1, column2 )
SELECT column1,column2
FROM source_table
create global temporary table temp_table_name
on commit preserve rows as select column1,column2,columnN from your_table;

Simple DB2 Query for connection validation

I'm looking for a simple DB2 query that can be used to test if a database connection in pool is still valid. It needs to be a generic query that would execute regardless of which databases exist.
For other database servers, I've used something like 'SELECT 1' or 'SELECT version();'
What would be an equivalent for DB2?
Thanks!
Try values 1.
Also, you can get the current date as
VALUES current date
or
SELECT current date FROM sysibm.sysdummy1
You can also get the version info as follows
SELECT service_level, fixpack_num, bld_level
FROM TABLE (sysproc.env_get_inst_info()) as A;