Can Sequel Create And Query Temp Tables - ruby

I am new to Sequel, but have a lot of background in SQL.
Getting frustrated with what I would call basic query functions not working. I am hoping it's a matter of just getting syntax correct.
I would like to create a temporary table, insert values into that table, then run a query against it.
In SQL I'd run this-
CREATE TABLE #TMP (CHRGCD VARCHAR)
INSERT INTO #TMP SELECT DISTINCT(CHRGCD) FROM PACPTCD WHERE CCTRMDT = '9999-01-01'
SELECT CHRGCD FROM PACPTCD
WHERE CHRGCD NOT IN (SELECT CHRGCD FROM #TMP)
Can I do this all from Sequel or am I going to have to create a real table, run a separate script to populate it, the run the last part of the query?
The data in the table PACPTCD can have multiple entries for CHRGCD but the CCTRMDT can vary. I'm trying to find all instances where CHRGCD doesn't have a value of 9999-01-01. Seems to be the easiest way to do it. Open to suggestions on other ways to get the data.

Thanks user007.
I ended up changing the query.
SELECT CHRGCD FROM PACPTCD
WHERE CHRGCD NOT IN (SELECT DISTINCT(CHRGC) FROM PACPTCD WHERE CCTRMDT='9999-01-01')
Dozen ways to do it. This one is the easiest. Even easier than my original.

Related

How to insert while avoiding unique constraints with oracle

We have a process that aggregates some data and inserts the results into another table that we use for efficient querying. The problem we're facing is that we now have multiple aggregators running at roughly the same time.
We use the original records id as the primary key in this new table - a unique constraint. However, if two aggregation processes are running at the same time, one of them will error with a unique constraint violation.
Is there a way to specify some kind of locking mechanism which will make the second writer wait until the first is finished? Alternatively, is there a way to tell oracle to ignore that specific row and continue with the rest?
Unfortunately it's not practical to reduce the aggregation to a single process, as the following procedures rely on an up to date version of the data being available and those procedures do need to scale out.
Edit:
The following is my [redacted] query:
INSERT INTO
agg_table
SELECT
h.id, h.col, h.col2
FROM history h
JOIN call c
ON c.callid = h.callid
WHERE
h.id > (SELECT coalesce(max(id),0) FROM agg_table)
It is possible run an INSERT statement with an error logging clause. The example from the Oracle docs is as follows:
INSERT INTO dw_empl
SELECT employee_id, first_name, last_name, hire_date, salary, department_id
FROM employees
WHERE hire_date > sysdate - 7
LOG ERRORS INTO err_empl ('daily_load') REJECT LIMIT 25
Alternatively, you could try using a [MERGE][2] statement. You would be merging into the summary table with a select from the detail table. If a match is not found, you INSERT and if it is found you would UPDATE. I believe this solution will handle your concurrency issues, but you would need to test it.
have a look at FOR UPDATE clause. If you correctly write the SELECT statement with FOR UPDATE clause within a transaction before your update/insert statements you will be able to "lock" the required records
Serialising the inserts is probably the best way, as there's no method that will get you round the problem of the multiple inserts being unable to see what each one is doing.
DBMS_Lock is probably the appropriate serialisation mechanism.

Stored Procedure: Cursor is bad?

I read somewhere that 99% of time you don't need to use a cursor.
But I can't think of any other way beside using a cursor in this following situation.
Select t.flag
From Dual t;
Let's say this return 4 rows of either 'Y' or 'N'. I want the procedure to trigger something if it finds 'Y'. I usually declare a cursor and loop until %NOTFOUND. Please tell me if there is a better way.
Also, if you have any idea, when is the best time to use a cursor?
EDIT: Instead of inserting the flags, what if I want to do "If 'Y' then trigger something"?
Your case definitely falls into the 99%.
You can easily do the conditional insert using insert into ... select.... It's just a matter or making a select that returns the result that you want to insert.
If you want to insert one record for each 'Y' then use a query with where flag = 'Y'. If you only want to insert a single record depending on whether there are at least one 'Y', then you can add distinct to the query.
A cursor is useful when you make something more complicated. I for example use a cursor when need to insert or update records in one table, and also for each record insert or update one or more records into several other tables.
Something like this:
INSERT INTO TBL_FLAG (col)
SELECT ID FROM Dual where flag = 'Y'
You will usually see a performance gain when using set based instead of procedural operations because most modern DBMS are setup to perform set based operations. You can read more here.
well the example doesnt quite make sense..
but you can always write an insert as select statement instead of what i think you are describing
Cursors are best to use when an column value form one table will be used repeatedly in multiple queries on different tables.
Suppose the values of id_test column are fetched from MY_TEST_TBL using a cursor CUR_TEST. Now this id_test column is a foreign key in MY_TEST_TBL. If we want to use id_test to insert or update any rows in table A_TBL,B_TBL and C_TBL, then in this case it's best to use cursors instead of using complex queries.
Hope this might help to understand the purpose of cursors

Executing triggers in Oracle for copying the old values to a Mirror table

We are trying to copy the current row of a table to mirror table by using a trigger before delete / update. Below is the working query
BEFORE UPDATE OR DELETE
ON CurrentTable FOR EACH ROW
BEGIN
INSERT INTO MirrorTable
( EMPFIRSTNAME,
EMPLASTNAME,
CELLNO,
SALARY
)
VALUES
( :old.EMPFIRSTNAME,
:old.EMPLASTNAME,
:old.CELLNO,
:old.SALARY
);
END;
But the problem is we have more than 50 coulmns in the current table and dont want to mention all those column names. Is there a way to select all coulmns like
:old.*
SELECT * INTO MirrorTable FROM CurrentTable
Any suggestions would be helpful.
Thanks,
Realistically, no. You'll need to list all the columns.
You could, of course, dynamically generate the trigger code pulling the column names from DBA_TAB_COLUMNS. But that is going to be dramatically more work than simply typing in 50 column names.
If your table happens to be an object table, :new would be an instance of that object so you could insert that. But it would be rather rare to have an object table.
If your 'current' and 'mirror' tables have EXACTLY the same structure you may be able to use something like
INSERT INTO MirrorTable
SELECT *
FROM CurrentTable
WHERE CurrentTable.primary_key_column = :old.primary_key_column
Honestly, I think that this is a poor choice and wouldn't do it, but it's a more-or-less free world and you're free (more or less :-) to make your own choices.
Share and enjoy.
For what it's worth, I've been writing the same stuff and used this to generate the code:
SQL> set pagesize 0
SQL> select ':old.'||COLUMN_NAME||',' from all_tab_columns where table_name='BIGTABLE' and owner='BOB';
:old.COL1,
:old.COL2,
:old.COL3,
:old.COL4,
:old.COL5,
...
If you feed all columns, no need to mention them twice (and you may use NULL for empty columns):
INSERT INTO bigtable VALUES (
:old.COL1,
:old.COL2,
:old.COL3,
:old.COL4,
:old.COL5,
NULL,
NULL);
people writing tables with that many columns should have no desserts ;-)

Passing SQL to an Oracle bind variable

I need to execute something like:
select
[very big SQL]
where phone_number in(:SQL2)
Is it possible to use bind variable for SQL2?
I want to save the execution plan of the major SQL.
Thanks.
Create a temporary table and save SQL2's results there prior to executing SQL1:
CREATE GLOBAL TEMPORARY TABLE mytemptable (id INT NOT NULL)
CREATE OUTLINE ol_sql1
ON
SELECT *
FROM sql1
WHERE id IN
(
SELECT id
FROM mytemptable
)
INSERT
INTO mytemptable
SELECT *
FROM sql2
SELECT *
FROM sql1
WHERE id IN
(
SELECT id
FROM mytemptable
)
If this query gets executed a lot of times, I wouldn't use a temporary table for it.
There is a 'trick' to bind an inlist, which Tom Kyte describes on his blog:
http://tkyte.blogspot.com/2006/06/varying-in-lists.html
I would bet on that being much more efficient. It should be easy to prove with a SQL Trace.
Further to Quassanoi's point. It sounds like you may not be familiar with temporary tables. This is a good introduction.
You only create the table once. Then within a given session you first:
populate the temporary table
execute your query pulling from the temporary table
rollback.
There's no risk of conflicting/overlapping with another session's data.

Oracle: LONG RAW to?

I am writing a program in java where I need to create a copy of a table (without data). for that I am using the following query
CREATE TABLE NEW_TABLE AS
SELECT * FROM OLD_TABLE
I have come across a table where one of the columns has the data type LONG RAW which is depricated.
I tried using the query below but it did not work. (ORA-01003: no statement parsed
)
CREATE TABLE NEW_TABLE AS
SELECT ID, COL1, COL2, TO_LOB(COL3) FROM OLD_TABLE
Can someone tell me a simple query for this. It should be able to store the values from the previous table. I am using oracle 10g
Thanks in advance.
EDIT:
Sorry it was my mistake, the above query worked fine but I was calling executeQuery instead of executeUpdate
Perhaps this discussion would help.
Sorry it was my mistake, the above query worked fine but I was calling executeQuery instead of executeUpdate which was throwing an SQLException

Resources