How to Create a Foreign Key from a Table to a Custom Datatype - oracle

Working with Oracle Express 11g, learning the interactions for object-relational databases.
Running into trouble while trying to create a foreign key from a normal table, to a table of a custom object (customers)
The customer object is as follows (customer_id NUMBER, fname VARCHAR2, lname VARCHAR2), for our setup, we wish to join a table Applications via customer_id NUMBER. Within the SQL Workshop, selecting the customers table is not even an option, and we cannot find syntax to manually create this relationship.
Any experts have some clues to help figure this one out?

create or replace type customer is object
(
customer_id NUMBER,
fname VARCHAR2(100),
lname VARCHAR2(100)
);
/
create table customers of customer
(
constraint customer_pk primary key(customer_id)
);
create table applications
(
application_id number,
customer_id number,
constraint applications_fk1 foreign key (customer_id)
references customers(customer_id)
);

Related

How to create a nested table of refs in Oracle SQL?

Consider the following problem:
There's the Transaction type and the Service type. Each transaction covers one or more services at a time. However, two different transactions may cover same services.
Now, it's pretty easy to consolidate this using relational database design. You'd have a table for transactions transaction id, and then some data fields, a table for services service id, some data fields and a third table that links transaction id's to service id's. This way, the service data is not duplicated and if you ever needed to, say, retrieve all services implicated in a transaction, you just do two joins transactions join third_table join service.
As far as I understand, ref simply stores the id of the record (object) it's pointing to and implicitly does a join upon deref(). So, say, if any of the transactions had to cover just one of the services, I could use a ref to the service object instead of the service id + an explicit join.
A nested table, as far as I understand, is just a private table that links the id of one object to a whole another object and that is shared among all objects of the type that declared the nested table. This concept also uses joins under the hood, if I'm not being horribly wrong. So if the services were unique among all transactions, I could in principle just use a nested table of services inside the transaction.
However, the problem is that there could be more than one service for every transaction and they could repeat. So the object-oriented solution, in my mind, is a nested table of ref to service inside of the transaction. However, I'm not able to find any clues on the Internet for the syntax for this idea and whether it is at all possible to do this.
Here's Oracle SQL sort of pseudocode (it doesn't work) of what I'm aiming for:
create type Service_Type as object(
id number(5),
-- some other data --
cost number(4),
name varchar2(32),
description varchar2(32)
---------------------
);
/
create table Service_Table of Service_Type (id primary key);
/
create type Service_Reference_Type as ref Service_Type scope is Service_Table;
/
create type Service_Reference_Table_Type as table of Service_Reference_Type;
/
create type Transaction_Type as object(
id number(5),
services Service_Reference_Table_Type,
-- some other data --
name varchar2(32),
description varchar2(32)
---------------------
);
nested table services store as Transaction_Service_Nested_Reference_Table;
/
As a sidenote: I know Object Oriented DBMS is garbage and I'm not planning on using it in any real project. This is for a university assignment (I wonder why they teach this stuff).
I don't think you're too far off, but you don't need Service_Reference_Type, you can create a table of refs in one step:
create type Service_Type as object(
id number(5),
-- some other data --
cost number(4),
name varchar2(32),
description varchar2(32)
---------------------
);
/
create table Service_Table of Service_Type (id primary key);
create type Service_Reference_Table_Type as table of ref Service_Type;
/
create type Transaction_Type as object(
id number(5),
services Service_Reference_Table_Type,
-- some other data --
name varchar2(32),
description varchar2(32)
---------------------
)
/
create table Transaction_Table of Transaction_Type
nested table services store as Transaction_Service_Nested_Reference_Table;
db<>fiddle including inserting and querying the data.
Is there a way one could scope the refs too?
As in the answer #MTO linked to:
alter table Transaction_Service_Nested_Reference_Table
add scope for (column_value) is Service_Table;
db<>fiddle

How do you create a multi-attribute table and link to the main table?

I have a table called customer. The customer, Here are the details for the table
Table name: customers
Attributes:
cus_id -- primary key
cus_street_num -- multi-attribute (home_address)
cus_street_name -- multi-attribute (home_address)
cus_suburb -- multi-attribute (home_address)
cus_gender
Here us my code for the customer table creation. But how do I create the multi-attribute and link it to the customer table?
What is a multi-attribute? For example a home address is a multi-attribute. Why? Because a home address is made up of 3 components. The street number, the street name and the suburb. These 3 things can be separate attributes, but they are useless without if they aren't together. However, together, they make up the home address.
CREATE TABLE customers (
cus_id NUMBER(5,0)
CONSTRAINT cus_id_pk
PRIMARY KEY (cus_id),
cus_gender NUMBER(1,0)
);

SQL Oracle - checking value in another table with CHECK or TRIGGER

Is any way, how to create table with CHECK (or maybe TRIGGER?), that will check, if inserted value is already in another table?
Example
CREATE TABLE Employee(
Name VARCHAR(10),
Adress VARCHAR(20)
);
CREATE TABLE Section(
Section_name VARCHAR(10),
Managers_name VARCHAR(10)
);
And I want to check, that value inserted to Managers_name is already in Employee, if it isnt, then print error.
I found any ways, how it could be done, but everything I tried in Oracle, didnt work.
Add a PRIMARY KEY constraint to the employee table and a FOREIGN KEY constraint to the section table:
CREATE TABLE Employee(
Name VARCHAR(10) CONSTRAINT Employee_Name_PK PRIMARY KEY,
Adress VARCHAR(20)
);
CREATE TABLE Section(
Section_name VARCHAR(10),
Managers_name VARCHAR(10)
CONSTRAINT section_manager_fk REFERENCES Employee( Name )
);
Check constraint is, as explained by mt0, devoted to single table.
Trigger is to be avoided for consistency reasons: while you're selecting a record, another session might be in the process of deleting it.
The Foreign Key is the correct way to implement it: Trap FK constraint violation in your code (ORA-02291 i guess), search for "section_manager_fk" in the message and finally rewrite a user-friendly error message.

How to declare an object as private

I am using following code to create an object
CREATE OR REPLACE TYPE sales_object IS OBJECT (
dates DATE,
product_id VARCHAR2(20),
product_name VARCHAR2(50),
sale DECIMAL(15,2)
);
which I am using to create a table with following code
CREATE OR REPLACE TYPE year_sales_tab IS TABLE OF sales_object;
Now this table is being used in a function to store and return a grid.
If there is any way to create the sales_object as private?
If there is any way to create the sales_object as private?
Yes.
Instead of creating type sales_object as OBJECT, create it as a RECORD in the package and use it in your code. When you create as an object, it is stored in the database, while if you create as a record, it could only be used in your code not elsewhere.
TYPE sales_object
IS
RECORD
(
DATES DATE,
PRODUCT_ID VARCHAR2(20),
PRODUCT_NAME VARCHAR2(50),
sale DECIMAL(15,2)
);
Update OP is actually talking about the privileges.
You could simply create the type by logging as the user to which you want the privileges to e given, by doing only the current user will have the owner privileges, while other users cannot access the object.
If you are intending to grant privilege to specific users, then
GRANT EXECUTE ON "USER"."TYPENAME" TO "OTHER_USER";

want an optimal solution for inserting more than one data in a single column of a single row

DROP TABLE District_Info;
CREATE TABLE District_Info(
Dname VARCHAR2(20) primary key,
Boundary_dist VARCHAR2(20)
);
for this code, for each Dname there are more than one Boundary_dist. it would be better if i could use an array of varchar2(20) and insert as much boundary_dist as i need to. want some helpful suggestions.
As already mentioned, the ideal way to do this would be to store an additional row for each DName/Boundary_Dist combination. The simplest way to do with a structure this simple is to just change your primary key:
CREATE TABLE District_Info(
Dname VARCHAR2(20) primary key,
Boundary_dist VARCHAR2(20) primary key);
If you're going to need other data in that table that has a 1:1 correlation to District, you would be better off splitting BoundayDist into a separate table:
CREATE TABLE District_Info(
Dname VARCHAR2(20) primary key,
Other_info VARCHAR2(20)
);
CREATE TABLE District_Boundary(
Dname VARCHAR2(20) primary key,
Boundary_dist VARCHAR2(20) primary key);
If you really insist on storing more that one value per row, you can use a user-defined datatype:
create type varchar_20_list as table of varchar2(20);
CREATE TABLE District_Info(
Dname VARCHAR2(20) primary key,
Boundary_dist varchar_20_list);
you need to create a separate table for Boundary_dist and create a foreign key which references the District_Info table.
Agreed, it'd be best to have Boundary_dist in a second table and connect them with an ID, but if you must typically what I do is store it as "1,2,3,4,5" that way in the code I can manipulate that pretty easily with PHP using explode or with mysql using IN.

Resources