Migration of Data in Oracle DB using SQL - sql

I have an issue with migration of data in Oracle DB during some release upgrades.
Case:
Table X in release 1 has three coulmns.
Same Table X in release 2 has five columns(two added in release 2).
Same table in release 3 has five columns as in release 2.
Upgrade paths include Release 1 to Release 3 and Release 2 to Release 3.
I need a Oracle SQL query which copies data from a TMP table to actual table in both cases based on coulmns size from TMP where i have stored the data temporarily(this has to be done).
Below is the query which i tried but it isnt working.
insert into USER.X values
(CASE (select count(*) from all_tab_columns where table_name='TMP')
WHEN '3' THEN (select USER.TMP.*, null NEWCOL1 from USER.TMP, null NEWCOL2 from USER.TMP)
WHEN '5' THEN (select USER.TMP.* from USER.TMP)
END
);
Please help in this regard and if there is a better way of doing the same please let me know.

Edit:
There are multiple problems in you logic.
You cannot determine number of parameters to insert statement at runtime. You have to determine it before creating insert statement.
Case returns only 1 value. More than that and you will get error
too many values
So you should
Create stored proc
Use if else and create insert statement based on
that.
Execute it by Execute immidiate
Prev. Response
The first problem in your query is that select count(*) from all_tab_columns where table_name='TMP' returns an integer, whereas in case you are comparing it to '3' and '5' as varchar. So assuming that rest of your query return result correctly, try replacing '3' and '5' as 3 and 5

Related

Missing expression Error with Insert Select query in Oracle SQL

i got this error with Oracle SQL with Insert Select query and don't where the error comes from
the SQL Query is:
insert into GroupScenarioAction (ID, ID_UUID, GPSCENARIO_UUID, ACTION, VERSION)
(select DEFAULT , '0', ACTION.ID_UUID, '5310AFAA......', '1', ACTION_ID, '0'
from ACTION where ACTION.id not in (select ACTION FROM GroupScenarioAction where
GPSCENARIO = '1'));
the error is ORA-00936: missing expression Position 129
It is difficult to assist because
you posted relevant data as images (why do you expect us to type all of that so that we could try it?) instead of code (which can easily be copy/pasted and used afterwards)
code you posted (the insert statement itself) uses columns that don't exist in any tables whose description you posted
for example, insert inserts into GroupScenarioAction, but there's no such table there; maybe it is goroohscenarioaction? Or, there's no action_id column in the action table
you're inserting values into 5 columns, but select statement contains 7 columns; that raises ORA-00913: too many values error, you don't even come to the missing expression error
Shortly, as if you tried to do everyhing you could to prevent us from helping you.
One of comments you posted says
It's the primary key so where are those values supposed to come from?
That's the default keyword in
insert into GroupScenarioAction (ID, ...)
(select DEFAULT, ...
-------
this
Looks like the ID column is created as an identity column whose value is autogenerated (i.e. Oracle takes care about it), which also means that you're on Oracle 12c or above (there was no such an option in lower versions). On the other hand create table goroohscenarioaction statement doesn't suggest anything like that.
Anyway: if you do it right, it works. I created two sample tables with a minimum column set, just to make insert work. Also, as I'm on 11gXE (which doesn't support identity columns, I'm inserting a sequence value which is, basically, what identity column uses in the background anyway):
SQL> create table groupscenarioaction
2 (id number,
3 id_uuid raw(255),
4 gpscenario_uuid raw(255),
5 action number,
6 version number
7 );
Table created.
SQL> create table action
2 (id_uuid raw(255),
3 id number
4 );
Table created.
SQL> create sequence seq;
Sequence created.
Insert you posted; I commented out columns that either don't exist or are superfluous. It works; though, didn't insert anything as my table(s) are empty, but it doesn't raise any error:
SQL> insert into GroupScenarioAction
2 (ID, ID_UUID, GPSCENARIO_UUID, ACTION, VERSION)
3 (select 1 /*DEFAULT*/ , '0', ACTION.ID_UUID, '5310AFAA......', '1' --, id /*ACTION_ID*/, '0'
4 from ACTION
5 where ACTION.id not in (select ACTION FROM GroupScenarioAction
6 where gpscenario_uuid/*GPSCENARIO*/ = '1'));
0 rows created.
Beautified:
SQL> insert into groupscenarioaction
2 (id, id_uuid, gpscenario_uuid, action, version)
3 (select seq.nextval, '0', a.id_uuid, '5310AFAA......', '1'
4 from action a
5 where a.id not in (select g.action
6 from groupscenarioaction g
7 where g.gpscenario_uuid = '1'));
0 rows created.
SQL>
Now that you know a little bit more about what's bothering use to help you, and if what I wrote isn't enough, consider editing the original question you posted (simply remove everything that's wrong and write something that is true and we can use).

Select into temp table

how to perform temp table in oracle from below script?
I tried usingselect * into #temp but it does not work. Please assist since i am new in oracle.
select * into temp from
(SELECT
CASE WHEN Aaddress = '16' THEN 'A'
ELSE 'OTHERS'
END AS PRODUCT
FROM NAME
WHERE name.INACTIVE_CODE IN ('1', '2'))
Oracle uses create table as:
create table temp as
SELECT (CASE WHEN Aaddress = '16' THEN 'A' ELSE 'OTHERS' END) AS PRODUCT
FROM NAME
WHERE name.INACTIVE_CODE IN ('1', '2');
Note if either Aaddress or INACTIVE_CODE are numbers, then the constants used for the comparisons should not have single quotes. Don't compare numbers to strings.
In SQL Server, #temp is a temporary table, but temp is not. In Oracle, you need to explicitly declare a temporary table:
create global temporary table temp as
Temporary tables in Oracle are created in advance, so that the definition is known before you use them.
So you could do
create global temporary table temp on commit preserve rows as select ... from ...
but this is not a recommendation to do this every time you run the query. More typical usage is specify the definition once:
create global temporary table temp (
col1 ...
col2 );
and then use INSERT to populate the table as required. By default, ie, as per my latter 'create' statement above, the moment you commit, the rows are lost. If you want to retain the rows after a commit, you add the 'on commit preserve rows' as per my first example. The reason you would have to do this in a create-table-as-select scenario is that otherwise your table would be created, populated with rows, and then immediately emptied as the command completes.

SQL data processing

I have an MS SQL database where sensor data is being streamed from a low level device, into say column 1.
In columns 2 and 3 I have some alarm levels.
What I would like to do is for "some script" to test the data as it arrives in column 1 against the levels in columns 2 and 3 and place a boolean decision in column 4.
My question is can I have some SQL script to do this? Where would it reside or does my low level device need knowledge of the column 2 and 3 trip points and when it posts the data to column 1 it also posts the decision to column 4?
UPDATE - First Test
I have implemented this and tested in sqlfiddle (but I am unable to login for some reason) so here is my schema:
CREATE TABLE SensorData(
data1 float NULL,
data1alarm bool NOT NULL DEFAULT FALSE
);
//
CREATE TABLE SensorConfig(
data1max float NULL,
data1min float NULL
);
//
CREATE TRIGGER Alarm
AFTER INSERT
ON SensorData FOR EACH ROW
BEGIN
IF (new.data1 > 5.0) AND (new.data1 < 60.0) THEN
INSERT INTO SensorData(data1alarm)
VALUES(true);
END IF;
END
//
INSERT INTO SensorConfig(data1max, data1min) VALUES (200.0, 100.0);
INSERT INTO SensorData(data1) VALUES (10.0);
When INSERT INTO SensorData(data1) VALUES (10.0); I get the error:
Can't update table 'sensordata' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
but when INSERT INTO SensorData(data1) VALUES (1.0); then the schema builds.
I cannot figure out the problem.
Also, I want really to implement such a condition that a true is written when data1 is greater data1max and less than data1min.
But at the moment I not sure why the schema does not build?
Furthermore, when I have tried getting the data1min and data1max into the conditional part of the trigger I have encountered errors:
IF (new.data1 > SensorConfig.data1min) AND (new.data1 < SensorConfig.data1max) THEN
Any help would be much appreciated.
I would recommend that you don't insert things into your table, but rather create a view that contains the logic for the alarm codes. So you might do
create view alarming_data as
select
data1.thevalue as theValue
true as theAlarm
from
data1 where data1.theValue > 5 and data1.theValue < 60
That keeps your raw data "pure" and your processing separate. In fact, you don't really need the second field, I'm just putting it there to keep my answer as close to your example as possible.
You can query this view as you would a table, and if your definition of alarming changes, it's just a matter of updating the definition of the view.
If you only want to display the offending lines, you don't need to persist column4, you can query them dynamically:
SELECT *
FROM mytable
WHERE column1 > column2 OR column1 > column3
You could create a trigger for that table with option AFTER INSERT
CREATE TRIGGER trDoMagic
ON YourTable
AFTER INSERT
your magic code

Query for first occurence of null value in SQLite

I have a table which I dynamically fill with some data I want to create some statistics for. I have one value which has some values following a certain pattern, so I created an additional column where I map the values to other values so I can group them.
Now before I run my statistics, I need to check if I have to remap these values which means that I have to check if there are null values in that column.
I can do a select like this:
select distinct 1
from my-table t
where t.status_rd is not null
;
The disadvantage is, that this returns exactly one row, but it has to perform a full select. Is there some way that I can stop the select for the first encounter? I'm not interested in the exact row, because when there is at least one row, I have to run an update on all of them anyway, but I would like to avoid running the update unnecessarily everytime.
In Oracle I would do it with rownum, but this doesn't exist in SQLite
select 1
from my-table t
where t.status_rd is not null
and rownum <= 1
;
Use LIMIT 1 to select the first row returned:
SELECT 1
FROM my_table t
WHERE t.status_rd IS NULL
LIMIT 1
Note: I changed the where clause from IS NOT NULL to IS NULL based on your problem description. This may or may not be correct.

select the rows affected by an update

If I have a table with this fields:
int:id_account
int:session
string:password
Now for a login statement I run this sql UPDATE command:
UPDATE tbl_name
SET session = session + 1
WHERE id_account = 17 AND password = 'apple'
Then I check if a row was affected, and if one indeed was affected I know that the password was correct.
Next what I want to do is retrieve all the info of this affected row so I'll have the rest of the fields info.
I can use a simple SELECT statement but I'm sure I'm missing something here, there must be a neater way you gurus know, and going to tell me about (:
Besides it bothered me since the first login sql statement I ever written.
Is there any performance-wise way to combine a SELECT into an UPDATE if the UPDATE did update a row?
Or am I better leaving it simple with two statements? Atomicity isn't needed, so I might better stay away from table locks for example, no?
You should use the same WHERE statement for SELECT. It will return the modified rows, because your UPDATE did not change any columns used for lookup:
UPDATE tbl_name
SET session = session + 1
WHERE id_account = 17 AND password = 'apple';
SELECT *
FROM tbl_name
WHERE id_account = 17 AND password = 'apple';
An advice: never store passwords as plain text! Use a hash function, like this:
MD5('apple')
There is ROW_COUNT() (do read about details in the docs).
Following up by SQL is ok and simple (which is always good), but it might unnecessary stress the system.
This won't work for statements such as...
Update Table
Set Value = 'Something Else'
Where Value is Null
Select Value From Table
Where Value is Null
You would have changed the value with the update and would be unable to recover the affected records unless you stored them beforehand.
Select * Into #TempTable
From Table
Where Value is Null
Update Table
Set Value = 'Something Else'
Where Value is Null
Select Value, UniqueValue
From #TempTable TT
Join Table T
TT.UniqueValue = T.UniqueValue
If you're lucky, you may be able to join the temp table's records to a unique field within Table to verify the update. This is just one small example of why it is important to enumerate records.
You can get the effected rows by just using ##RowCount..
select top (Select ##RowCount) * from YourTable order by 1 desc