How to find a view for a certain table in Informix? - datatable

I have a database with loads of tables and views and I want to find out which view belongs to a certain table if this is even possible. The database I use is IBM Informix.

The answer you seek is encoded in the "informix".sysdepend table in the system catalog.
Table 1. SYSDEPEND table column descriptions
Column.
Type.
Explanation
btabid
INTEGER
Code uniquely identifying the base table or view
btype
CHAR(1)
Base object type: T = Table V = View
dtabid
INTEGER
Code uniquely identifying a dependent table or view
dtype
CHAR(1)
Code for the type of dependent object; currently, only view (V = View) is implemented
So, given the tabid value from "informix".systables (which might identify a base table or a view), you can find out which other views depend on it. You will probably need to join with systables several times.
For example:
SELECT * FROM SysDepend;
btabid
btype
dtabid
dtype
INTEGER
CHAR(1)
INTEGER
CHAR(1)
30
T
70
V
3
T
71
V
296
T
299
V
297
T
300
V
298
T
301
V
318
T
320
V
318
T
325
V
SELECT d.btabid, t1.owner, t1.tabname, d.btype, d.dtabid, d.dtype, t1.owner, t2.tabname
FROM "informix".SysDepend AS d
JOIN "informix".SysTables AS t1 ON d.btabid = t1.tabid
JOIN "informix".SysTables AS t2 ON d.dtabid = t2.tabid
ORDER BY t1.owner, t1.tabname, t2.owner, t2.tabname;
btabid
owner
tabname
btype
dtabid
dtype
owner
tabname
INTEGER
CHAR(32)
VARCHAR(128)
CHAR(1)
INTEGER
CHAR(1)
CHAR(32)
VARCHAR(128)
298
informix
sysbldiprovided
T
301
V
informix
bldi_provided
297
informix
sysbldirequired
T
300
V
informix
bldi_required
296
informix
sysbldregistered
T
299
V
informix
bld_registered
3
informix
sysindices
T
71
V
informix
sysindexes
30
informix
sysxtdtypes
T
70
V
informix
sysdomains
318
sde
spatial_references
T
320
V
sde
spatial_ref_sys
318
sde
spatial_references
T
325
V
sde
spatial_references_expand

Related

What is the most efficient way to update values of a table based on a mapping from another table

I have a table including following details.
empID department location segment
1 23 55 12
2 23 11 12
3 25 11 39
I also have a mapping table like following
Field old value new value
Department 23 74
department 25 75
segment 10 24
location 11 22
So My task is to replace old values with new values. I can actually use a cursor and update departments first then segments so on and so forth . But that is time consuming and inefficient. I would like to know if there are any efficient way to do this. Which also need to support in future if we were plan to add more columns to the mapping.
cheers.
Check this if it solves the issue.
update emp set department = (select map.new_value from map where emp.department = map.old_value);
How about copying the data to a new table?
CREATE TABLE newemp AS
SELECT e.empid,
NVL(d.new_value, e.department) AS department,
NVL(l.new_value, e.location) AS location,
NVL(s.new_value, e.segment) AS segment
FROM emp e
LEFT JOIN map d ON d.field='DEPARTMENT' AND e.department = d.old_value
LEFT JOIN map l ON l.field='LOCATION' AND e.location = d.old_value
LEFT JOIN map s ON s.field='SEGMENT' AND e.segment = d.old_value
ORDER BY e.empid;
EMPID DEPARTMENT LOCATION SEGMENT
1 84 55 12
2 84 11 12
3 75 11 39
You'll need obviously three passes through the mapping table, but only one pass through the emp table.
We use a LEFT JOIN because not all values will be changed. If no new_value is found, the NVL function uses the existing value of the emp table.
You could update the original table from this new table (if the new table has a primary key):
UPDATE (SELECT empid,
e.department as old_department,
n.department as new_department,
e.location as old_location,
n.location as new_location,
e.segment as old_segment,
n.segment as new_segment
FROM emp e
JOIN newemp n USING (empid))
SET old_department = new_department,
old_location = new_location,
old_segment = new_segment
WHERE old_department != new_department
OR old_location != new_location
OR old_segment != new_segment;

What is the exact NULL value for a field in Oracle?

Title says it all pretty much. What is the exact value that is assigned to a(n) a)Arithmetic b)String c)Logical field to represent NULL, in Oracle DBMS?
Thank you for your time!
Null is the absence of meaning, the absence of value. What gets assigned is null. Not even an ASCII null (ascii value 0) but nothing.
That's why there's a special operation to test for null . This will return false:
...
where col1 = null
We need to test for:
where col1 is null
"we were asked by a professor at uni to find what exactly that value is in these 3 respective cases"
Okay, let's investigate that. Here is a table with two rows:
SQL> create table t42 (
2 type varchar2(10)
3 , colv varchar2(10)
4 , coln number
5 , cold date
6 )
7 /
Table created.
SQL> insert into t42 values ('not null', 'X', 1, sysdate);
1 row created.
SQL> insert into t42 values ('all null', null, null, null);
1 row created.
SQL>Exp
Oracle has a function dump() which shows us the datatype and content of the passed value. Find out more.
What does dump() tell us about our two rows?
SQL> select type
2 , dump(colv) as colv
3 , dump(coln) as coln
4 , dump(cold) as cold
5 from t42;
TYPE COLV COLN COLD
---------- -------------------- -------------------- ----------------------------------
not null Typ=1 Len=1: 88 Typ=2 Len=2: 193,2 Typ=12 Len=7: 120,117,4,29,6,60,44
all null NULL NULL NULL
SQL>
So: the null columns have no data type, no value.
"I don't think dump is suitable for supporting any argument over what "exactly" gets stored to represent a null - because if the expression is null, it simply returns null by definition "
#JeffreyKemp makes a fair point. So let's dip a toe into the internals. The first step is to dump the data block(s);l the dump is written to a trace file:
SQL> conn / as sysdba
Connected.
USER is "SYS"
SQL> select dbms_rowid.rowid_relative_fno(t42.rowid) as fno
2 , dbms_rowid.rowid_block_number(t42.rowid) as blk
3 from a.t42
4 /
FNO BLK
-------- --------
11 132
11 132
SQL> alter system dump datafile 11 block 132;
System altered.
SQL> select value from v$diag_info where name = 'Default Trace File';
VALUE
--------------------------------------------------------------------------------
/home/oracle/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_3275.trc
SQL>
Because T42 is small it fits into only one block. Here is the interesting bit of the dump:
data_block_dump,data header at 0x805664
===============
tsiz: 0x1f98
hsiz: 0x16
pbl: 0x00805664
76543210
flag=--------
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x1f73
avsp=0x1f5d
tosp=0x1f5d
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0x1f7f
0x14:pri[1] offs=0x1f73
block_row_dump:
tab 0, row 0, #0x1f7f
tl: 25 fb: --H-FL-- lb: 0x1 cc: 4
col 0: [ 8] 6e 6f 74 20 6e 75 6c 6c
col 1: [ 1] 58
col 2: [ 2] c1 02
col 3: [ 7] 78 75 05 01 02 08 08
tab 0, row 1, #0x1f73
tl: 12 fb: --H-FL-- lb: 0x1 cc: 1
col 0: [ 8] 61 6c 6c 20 6e 75 6c 6c
end_of_block_dump
End dump data blocks tsn: 33 file#: 11 minblk 132 maxblk 132
We can see there are two rows in the table. The first row has entries for four columns; this is the 'not null' row. The second row has only one column: this is the 'all null' row. So, Jeffrey is quite right. All the trailing fields are null so Oracle stores nothing for them.
Answer from APC is fully right, let's give some information on "what does it mean":
Arithmetic: NULL basically means "not defined". Every math operation with NULL (i.e. "not defined") also returns NULL
String: NULL is an empty string, i.e. '' IS NULL returns TRUE - this behavior of Oracle is different to many others RDBMS.
Logical: I assume you mean what happens to BOOLEAN data types. Unlike almost any other programming language in PL/SQL a BOOLEAN variable can have three different states: TRUE, FALSE and NULL. Be aware of this special behavior when you work with BOOLEAN in PL/SQL.
In addition to #APC, in DB there is a something like 'ternary logic' in comparison operations, when we can say that value are equal, not equal and the third is "we don't know", cause of it value absence NULL, and even comparison of to NULL values gives the NULL, meaning that we have no information about operands

Oracle:To realize the column automatic management

dataSource:
username type rank
a 106 1
a 116 2
a 126 3
b 106 1
b 106 2
when remove a,116,2 this record return:
username type rank
a 106 1
a 126 2
b 106 1
b 106 2
when insert a,116 return:
username type rank
a 106 1
a 126 2
a 116 3
b 106 1
b 106 2
I choose use tigger to realize:
insert(succeed):
create or replace trigger bi_auto
before insert
on auto
for each row
declare
-- local variables here
begin
select count(rank)+1 into :new.rank from auto where username=:new.username;
end bi_auto;
delete(fail,return ora-04091, ora-06512, ora-04088):
create or replace trigger bd_auto
after delete
on auto
for each row
declare
-- local variables here
begin
insert into session_auto
select username, type, rank() over(partition by username order by rank) ranknew from auto where username=:old.username order by username;
delete from auto where username=:old.username;
insert into auto select * from session_auto;
end bd_auto;
Please help me to modify it,thanks.I know there is something wrong with the performance, but I want to know how to realize.
I think the entire approach is problematic and error prone. It would be much easier to calculate the rank dynamically. If you want the convenience of querying a table, you could just add it to a view:
CREATE OR REPLACE VIEW auto_view AS
SELECT username, type, RANK() OVER (PARTITION BY username ORDER BY TYPE ASC) r
FROM auto
If performance is that big of an issue, you could always materialize your view.

Oracle - Insert x amount of rows with random data

I am currently doing some testing and am in the need for a large amount of data (around 1 million rows)
I am using the following table:
CREATE TABLE OrderTable(
OrderID INTEGER NOT NULL,
StaffID INTEGER,
TotalOrderValue DECIMAL (8,2)
CustomerID INTEGER);
ALTER TABLE OrderTable ADD CONSTRAINT OrderID_PK PRIMARY KEY (OrderID)
CREATE SEQUENCE seq_OrderTable
MINVALUE 1
START WITH 1
INCREMENT BY 1
CACHE 10000;
and want to randomly insert 1000000 rows into it with the following rules:
OrderID needs to be be sequential (1, 2, 3 etc...)
StaffID needs to be a random number between 1 and 1000
CustomerID needs to be a random number between 1 and 10000
TotalOrderValue needs to be a random decimal value between 0.00 and 9999.99
Is this even possible to do? I can I could generate all of these using this update statement? however generating a million rows in 1 go I am not sure on how to do this
Thanks for any help on this matter
This is how i would randomly generate the number on update:
UPDATE StaffTable SET DepartmentID = DBMS_RANDOM.value(low => 1, high => 5);
For testing purposes I created the table and populated it in one shot, with this query:
CREATE TABLE OrderTable(OrderID, StaffID, CustomerID, TotalOrderValue)
as (select level, ceil(dbms_random.value(0, 1000)),
ceil(dbms_random.value(0,10000)),
round(dbms_random.value(0,10000),2)
from dual
connect by level <= 1000000)
/
A few notes - it is better to use NUMBER as data type, NUMBER(8,2) is the format for decimal. It is much more efficient for populating this kind of table to use the "hierarchical query without PRIOR" trick (the "connect by level <= ..." trick) to get the order ID's.
If your table is created already, insert into OrderTable (select level...) (same subquery as in my code) should work just as well. You may be better off adding the PK constraint only after you create the data though, so as not to slow things down.
A small sample from the table created (total time to create the table on my cheap laptop - 1,000,000 rows - was 7.6 seconds):
SQL> select * from OrderTable where orderid between 500020 and 500030;
ORDERID STAFFID CUSTOMERID TOTALORDERVALUE
---------- ---------- ---------- ---------------
500020 666 879 6068.63
500021 189 6444 1323.82
500022 533 2609 1847.21
500023 409 895 207.88
500024 80 2125 1314.13
500025 247 3772 5081.62
500026 922 9523 1160.38
500027 818 5197 5009.02
500028 393 6870 5067.81
500029 358 4063 858.44
500030 316 8134 3479.47

How to find Max value of an alphanumeric field in oracle?

I have the data as below and ID is VARCHAR2 type
Table Name :EMP
ID TST_DATE
A035 05/12/2015
BAB0 05/12/2015
701 07/12/2015
81 07/12/2015
I used below query to get max of ID group by TST_DATE.
SELECT TST_DATE,MAX(ID) from EMP group by TST_DATE;
TST_DATE MAX(ID)
05/12/2015 BAB0
07/12/2015 81
In the second row it returning 81 instead of 701.
To sort strings that represent (hex) numbers in numeric, rather than lexicographical, order you need to convert them to actual numbers:
SELECT TST_DATE, ID, TO_NUMBER(ID, 'XXXXXXXXXX') from EMP
ORDER BY TO_NUMBER(ID, 'XXXXXXXXXX');
TST_DATE ID TO_NUMBER(ID,'XXXXXXXXXX')
---------- ---- ---------------------------------------
07/12/2015 81 129
07/12/2015 701 1793
05/12/2015 A035 41013
05/12/2015 BAB0 47792
You can use that numeric form within your max() and convert back to a hex string for display:
SELECT TST_DATE,
TO_CHAR(MAX(TO_NUMBER(ID, 'XXXXXXXXXX')), 'XXXXXXXXXX')
from EMP group by TST_DATE;
TST_DATE TO_CHAR(MAX
---------- -----------
07/12/2015 701
05/12/2015 BAB0
With a suitable number of Xs in the format models of course; how many depends on the size of your varchar2 column.

Resources