Assign formats/informats for Oracle dataset in SAS - oracle

I use SAS/ACCESS path-through facility in order to create a table in Oracle:
proc sql;
connect to oracle(user=mylogin orapw=mypw path=mypath);
execute (
create table FCFCORE.RUS_FSC_RATE
( DATE_KEY NUMBER(8),
RATE NUMBER(20,10),
)
) by oracle;
disconnect from oracle;
quit;
When in EG I check properties of the table I see that DATE_KEY has format/informat 9., and RATE has informat 22.10. How can I change these formats?
If I use proc datasets the following error occures: ERROR: The HEADER/VARIABLE UPDATE function is not supported by the ORACLE engine.

You can use the DBSASTYPE data step option to override the default.
Example:
proc append base=dblib.hrdata (dbsastype=(empid='CHAR(20)'))
data=saslib.personnel;
run;

Related

create a random uuid function and use it to generate column value in oracle [duplicate]

I am trying to update a table in Oracle. The table is created using following DDL:
CREATE TABLE TEST (
ID_NUM INTEGER,
NAME INTEGER,
VALUE INTEGER,
ITEMS_NUM INTEGER,
)
And there were some data injected into this table. Now, I need to update the table to change the ID_NUM column as VARCHAR and add formatted UUID as default value.
I have followed the queries given below:
CREATE OR REPLACE FUNCTION RANDOM_UUID RETURN VARCHAR IS
V_UUID VARCHAR(255);
BEGIN
SELECT REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5') INTO V_UUID FROM DUAL;
RETURN V_UUID;
END RANDOM_UUID;
ALTER TABLE TEST
DROP COLUMN ID_NUM;
ALTER TABLE TEST
ADD ID_NUM VARCHAR(255) DEFAULT random_uuid() NOT NULL;
It gives an error as SQL Error [4044] [42000]: ORA-04044: procedure, function, package, or type is not allowed here
I have executed and validated the function using following command and it gives a valid formatted UUID.
SELECT RANDOM_UUID() FROM DUAL;
What could be the issue in the ALTER table statement. Can't we use a function for setting default value in Oracle?
Thanks in advance.
I think you can achieve it using the default clause on the column but without function (just replace the function call with the content of the function in default clause) as following. (Please note that the User functions are not allowed in the default clause)
ALTER TABLE TEST
ADD ID_NUM VARCHAR(255)
DEFAULT REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5')
NOT NULL;
I have prepared the db<>fiddle demo to show you the error with function and success without function.
Cheers!!
You cannot use PL/SQL functions in the default expression. But it can be a SQL function.Here's an extract from the 19c Doc:
Default column values are subject to the following restrictions:
A DEFAULT expression cannot contain references to PL/SQL functions or
to other columns, the pseudocolumns LEVEL, PRIOR, and ROWNUM, or date
constants that are not fully specified.
And here's an example using a sql function:
SQL> create table tc (c1 number default sqrt(2));
Table TC created.
The default value has to be an actual value, not a function.

Combining sets+tables+windowfunction in one go

I want to make something like this work in proc sql:
proc sql;
%connect_to_sql_macro;
create table sql.table as
(
select some_id, date from connection to oracle
(
select some_id, date, row_number()over(partition by some_id order by date) as row from dataset d join sql_table s on d.some_id=s.some_id
) where row=1
Basically i need to create table in oracle based on dataset joined with oracle table and take the first date for each id.
If i use "from oracle" pass through it doesn't see the dataset, if i make it the other way around i can't use window functions(row_number()) becouse they are not in SAS. For now i create a table from that dataset and then do a pass through but it's large and i need to do it in one go. Any suggestions?
You're probably better off doing it in SAS.
Can be done in one step too
libname lib <oracle connection options>;
proc sql;
select some_id
,date
from dataset d
inner join lib.sql_table s
on d.some_id=s.some_id
group by some_id
having date=min(date)
;
quit;
or
proc sql;
%connect_to_sql_macro;
select some_id
,date
from dataset d
inner join (select * from connection to oracle (
select * from sql_table
)
) s
on d.some_id=s.some_id
group by some_id
having date=min(date)
;
quit;
Also, limit as much as you can the amount of records that are being read from the oracle table.

Want to create Stored Procedure of new table with calculated variable

I want to create a stored procedure using the table from Oracle and want to access in SAS EG.
I have below code .
create table xyz as
select * from (
select a,b,c,d
from table_name
)
pivot (MIN('X') for Variable_name in (
'PQR' as PQR, 'PGT' as PGT, 'KLD' as KLD,
'opd' as opd
)
)
order by Variable_name;
Is it possible to make this table as stored procedure? And if not then please suggest solution.
If I'm understanding your problem correctly you should be able to do this using SQL pass-through. You will just need to specify the Oracle database in the libname statement in SAS which will look something like this:
libname mydblib oracle user=user_name password=pw path='myoracleserver';
You can then access this using proc sql in SAS.
proc sql;
connect using mydblib;
create table xyz as
select * from connection to mydblib (
select * from (
select a,b,c,d
from table_name
)
pivot (MIN('X') for Variable_name in (
'PQR' as PQR, 'PGT' as PGT, 'KLD' as KLD,
'opd' as opd
)
)
order by Variable_name
);
quit;
This code creates the table xyz in your SAS work library.

How can to retrieve and write the BLOB in my storage in oracle

I have a table with this script:
CREATE TABLE PRSNL_IMG
(
PER_IMG LONG RAW,
NATIONAL_COD NUMBER
);
Now I want to retrieve and write the BLOB ( PER_IMG type: LONG RAW ) into a file with name "NATIONAL_COD" on path on hard sush as "D:\Photo_OUT\" from the database with name .My table have 82000 records.I have work with form6i and my database version is oracle 11g.
please help me.
You can create a table with BLOB like this
CREATE GLOBAL TEMPORARY TABLE foo (
b BLOB);
INSERT INTO foo VALUES ('1f8b080087cdc1520003f348cdc9c9d75128cf2fca49d1e30200d7bbcdfc0e000000');
and just select it
SELECT b FROM foo;
-- (BLOB)
SELECT UTL_RAW.CAST_TO_RAW(UTL_RAW.CAST_TO_VARCHAR2(b))
FROM foo;
-- 1F8B080087CDC1520003F348CDC9C9D75128CF2FCA49D1E30200D7BBCDFC0E000000
If the content is not too large, you can also use
SELECT CAST ( <blobfield> AS RAW( <maxFieldLength> ) ) FROM <table>;

How to compare two Oracle schemas to get delta changes by Altering the table not to drop and recreate it

I've already tried out a tool named TOYS. I found it free but unfortunately it didn't work.
Then, I tried "RED-Gate Schema Compare for Oracle" but it uses the technique to drop and recreate the table mean while I need to just alter the table with the newly added/dropped columns.
Any help is highly appreciated
Thanks
Starting from Oracle 11g you could use dbms_metadata_diff package and specifically compare_alter() function to compare metadata of two schema objects:
Schema #1 HR
create table tb_test(
col number
)
Schema #2 HR2
create table tb_test(
col_1 number
)
select dbms_metadata_diff.compare_alter( 'TABLE' -- schema object type
, 'TB_TEST' -- object name
, 'TB_TEST' -- object name
, 'HR' -- by default current schema
, 'HR2'
) as res
from dual;
Result:
RES
-------------------------------------------------
ALTER TABLE "HR"."TB_TEST" ADD ("COL_1" NUMBER);
ALTER TABLE "HR"."TB_TEST" DROP ("COL");

Resources