Redact function not working in Oracle SQL Developer - sql

Summary of Post: I tried to full redact the TITLE column, but it's not working even though the script is executing just fine. I just want the data from the TITLE column in the FACULTY table to be redacted and not visible to users who aren't secmgr.
Hello, Below is my code and it executes perfectly (or so I thought). No error messages appear, but when I go to check if the redact policy works, I find that the data is not being redacted and it is is still visible. I check the priviledges of the test account (OO) but it hasn't been granted any privileged other thatn create session and select. Please help.
set echo on
show user;
---- Clean up workspace
drop table STUDENT;
drop table FACULTY;
drop table OFFERING;
drop table ENROLLMENT;
drop user oo;
drop user secmgr cascade;
drop user sysmgr cascade;
drop user u1;
drop user u2;
drop role pr;
---- Create the tables using DDL
create table STUDENT(
STUDENTID number(3) not null,
NAME varchar(10),
MAJOR varchar(20),
STATUS char(2),
ADDRESS varchar(15),
GPA number(3,2)
);
create table FACULTY(
FACULTYID number(4),
NAME varchar(10),
ORGCD varchar (3),
ADDRESS varchar(15),
CC number(16),
SALARY number (7),
RANK varchar(12),
TITLE varchar (4)
);
create table OFFERING(
OFFERINGNUM number(4) not null,
COURSENUM char(5),
FACULTYID number(4),
TERM varchar(6),
YEAR char(4),
TIME varchar(8)
);
create table ENROLLMENT(
OFFERINGNUM number(4) not null,
STUDENTID number(3) not null
);
---- Populate the tables with data and check using DML
insert all
into STUDENT (STUDENTID, NAME, MAJOR, STATUS, ADDRESS, GPA) values (100, 'ABLE', 'HISTORY', 'SR', '1 UTAH', 3.00)
into STUDENT (STUDENTID, NAME, MAJOR, STATUS, ADDRESS, GPA) values (200, 'BAKER', 'ACCOUNTING', 'JR', '2 IOWA', 2.70)
into STUDENT (STUDENTID, NAME, MAJOR, STATUS, ADDRESS, GPA) values (300, 'CHARLES', 'MATH', 'SR', '3 MAINE', 3.50)
into STUDENT (STUDENTID, NAME, MAJOR, STATUS, ADDRESS, GPA) values (400, 'DRAKE', 'COMPUTER SCIENCEY', 'FR', '4 IDAHO', 2.80)
into STUDENT (STUDENTID, NAME, MAJOR, STATUS, ADDRESS, GPA) values (500, 'ELLIOT', 'COMPUTER SCIENCEY', 'SM', '5 NEVADA', 3.25)
SELECT * FROM dual;
SELECT * FROM STUDENT;
insert all
into FACULTY (FACULTYID, NAME, ORGCD, ADDRESS, CC, SALARY, RANK, TITLE) values (0980, 'MARTIN', 'IM', '11 MAIN', 4560123450001234, 250000, 'DEAN', 'CEO')
into FACULTY (FACULTYID, NAME, ORGCD, ADDRESS, CC, SALARY, RANK, TITLE) values (5430, 'SEAVER', 'IS', '12 SOUTH', 4560123450002345, 180000, 'PROFESSOR', 'CIO')
into FACULTY (FACULTYID, NAME, ORGCD, ADDRESS, CC, SALARY, RANK, TITLE) values (7650, 'LOONEY', 'IT', '14 NORTH', 4560123450003456, 160000, 'INSTRUCTOR', 'CISO')
into FACULTY (FACULTYID, NAME, ORGCD, ADDRESS, CC, SALARY, RANK, TITLE) values (9870, 'MILLS', 'SA', '16 EAST', 4560123450004567, 90000, 'LECTURER', 'CFO')
into FACULTY (FACULTYID, NAME, ORGCD, ADDRESS, CC, SALARY, RANK, TITLE) values (9990, 'BOND', 'INT', '007 NE', 4560123450005678, 90000, 'COACH', 'SPY')
SELECT * FROM dual;
SELECT * FROM FACULTY;
insert all
into OFFERING (OFFERINGNUM, COURSENUM, FACULTYID, TERM, YEAR, TIME) values (1111, 'IS320', 5430, 'FALL', '2012', '10 AM')
into OFFERING (OFFERINGNUM, COURSENUM, FACULTYID, TERM, YEAR, TIME) values (1233, 'IS320', 0980, 'FALL', '2012', '11 AM')
into OFFERING (OFFERINGNUM, COURSENUM, FACULTYID, TERM, YEAR, TIME) values (2222, 'IS460', 7650, 'SPRING', '2013', '10 AM')
into OFFERING (OFFERINGNUM, COURSENUM, FACULTYID, TERM, YEAR, TIME) values (3333, 'IT480', 5430, 'SPRING', '2013', '11 AM')
SELECT * FROM dual;
SELECT * FROM OFFERING;
insert all
into ENROLLMENT (OFFERINGNUM, STUDENTID) values (1111, 100)
into ENROLLMENT (OFFERINGNUM, STUDENTID) values (1233, 500)
into ENROLLMENT (OFFERINGNUM, STUDENTID) values (2222, 300)
into ENROLLMENT (OFFERINGNUM, STUDENTID) values (3333, 400)
SELECT * FROM dual;
SELECT * FROM ENROLLMENT;
-- User created for testing redaction
create user oo identified by o;
grant create session to oo
grant select on FACULTY to oo;
-- Create a security manager who will create the redact policy
show user;
create user secmgr identified by s;
grant dba to secmgr;
grant create session to secmgr;
create user sysmgr identified by s2;
grant dba to sysmgr;
grant create session to sysmgr;
connect sysmgr/s2;
connect sys/ as sysdba;
grant execute on dbms_redact to secmgr;
-- Create the policy (full redact)
-- cleanup workspace
begin
dbms_redact.drop_policy (
object_schema => 'DBST_USER',
object_name => 'FACULTY',
policy_name => 'FACULTY_POL'
);
end;
/
connect secmgr/s;
begin
dbms_redact.add_policy
(object_schema => 'DBST_USER',
object_name => 'FACULTY',
policy_name => 'FACULTY_POL',
column_name => 'TITLE',
function_type => DBMS_REDACT.FULL,
expression => '1=1');
end;
/
connect oo/o;
select * from dbst_user.FACULTY;
I also checked to see if the policy was active and found the following; apparently, the FACULTY_POL is active, multiple times despite my dropping the policy. I can't seem to get rid of them. I have a feeling this is causing the problem.

Related

Analytical Query in SQL for MIN, MAX, and AVG

I am trying to figure out a query for this question: for each major, list the number of students, minimum GPA, maximum GPA, average GPA, minimum age, maximum age, and average age. (Show GPA with 2 decimal points, age with no decimal points. You may find it useful to create a view with one of the previous queries for this one.)
This is the script to create the table for SQL!
REM drop all the tables. Note that you need to drop the
REM dependent table first before dropping the base tables.
drop table Reg;
drop table Student;
drop table Course;
REM Now create all the tables.
create table Student
(
sid char(10) primary key,
sname varchar(20) not null,
gpa float,
major char(10),
dob DATE
);
create table Course
(
cno char(10) primary key,
cname varchar(20) not null,
credits int,
dept char(10)
);
create table Reg
(
sid references Student(sid) on delete cascade,
cno references Course(cno) on delete cascade,
grade char(2),
primary key (sid, cno)
);
REM Now insert all the rows.
insert into Student values ('111', 'Joe', 3.5 , 'MIS', '01-AUG-2000');
insert into Student values ('222', 'Jack', 3.4 , 'MIS', '12-JAN-1999');
insert into Student values ('333', 'Jill', 3.2 , 'CS', '15-MAY-1998');
insert into Student values ('444', 'Mary', 3.7 , 'CS', '17-DEC-2001');
insert into Student values ('555', 'Peter', 3.8 , 'CS', '19-MAR-1999');
insert into Student values ('666', 'Pat', 3.9, 'Math', '31-MAY-2000');
insert into Student values ('777', 'Tracy', 4.0, 'Math', '18-JUL-1997');
insert into Course values ('c101', 'intro', 3 , 'CS');
insert into Course values ('m415', 'database', 4 , 'Bus');
insert into Course values ('m215', 'programming', 4 , 'Bus');
insert into Course values ('a444', 'calculus', 3 , 'Math');
insert into Reg values ('111', 'c101', 'A');
insert into Reg values ('111', 'm215', 'B');
insert into Reg values ('111', 'm415', 'A');
insert into Reg values ('222', 'm215', 'A');
insert into Reg values ('222', 'm415', 'B');
insert into Reg values ('333', 'c101', 'A');
insert into Reg values ('444', 'm215', 'C');
insert into Reg values ('444', 'm415', 'B');
insert into Reg values ('555', 'c101', 'B');
insert into Reg values ('555', 'm215', 'A');
insert into Reg values ('555', 'm415', 'A');
insert into Reg values ('666', 'c101', 'A');
This is what I have so far:
SELECT major,
count(distinct SID) as students,
round(min(gpa), 2),
round(max(gpa), 2),
round(avg(gpa), 2),
trunc(min(sysdate - dob)/365) as min_age,
trunc(max(sysdate - dob)/365) as max_age,
trunc(avg(sysdate - dob)/365) as avg_age,
FROM Student
GROUP BY MAJOR;
According to your input I've made a query that I belive will show you the results. (It was kind hard to read the tables the way you posted it). The syntax may differ according to your DBMS (SQL Server, MySQL, REdshift, Postgres, etc)
Here is the query:
SELECT major,
COUNT(*) as students,
ROUND(MIN(gpa), 2) as min_gpa,
ROUND(MAX(gpa), 2) as max_gpa,
ROUND(AVG(gpa), 2) as avg_gpa,
MIN(DATEDIFF(year, current_date, dob)) as min_age,
MAX(DATEDIFF(year, current_date, dob)) as max_age,
AVG(DATEDIFF(year, current_date, dob)) as avg_date
FROM students st left join Course co on co.dept = st.major
GROUP BY major
Your query is completely fine (just remove comma(,) after avg_age.
SELECT major,
count(distinct SID) as students,
round(min(gpa), 2) as MinGPA,
round(max(gpa), 2) as MaxGPA,
round(avg(gpa), 2) as AvgGPA,
round(min(sysdate - dob)/365,0) as min_age,
round(max(sysdate - dob)/365,0) as max_age,
round(avg(sysdate - dob)/365,0) as avg_age
FROM Student
GROUP BY MAJOR;
You can also use months_between() with floor() to get the same result:
select * from student;
SELECT major,
count(distinct SID) as students,
round(min(gpa), 2) as MinGPA,
round(max(gpa), 2) as MaxGPA,
round(avg(gpa), 2) as AvgGPA,
floor(min(months_between(trunc((sysdate)), dob)) /12) as min_age,
floor(max(months_between(trunc((sysdate)), dob)) /12) as max_age,
floor(avg(months_between(trunc((sysdate)), dob)) /12) as avg_age
FROM Student
GROUP BY MAJOR;

Oracle SQL Developer data format

I have created a table 'USER' in Oracle SQL Developer.
CREATE TABLE USER(
USER_ID INTEGER NOT NULL,
FIRST_NAME VARCHAR2(50) NOT NULL,
LAST_NAME VARCHAR2(50) NOT NULL,
ID_CODE INTEGER NOT NULL,
DATE_OF_BIRTH TIMESTAMP NOT NULL,
TRAINING_CLUB VARCHAR2(50) NOT NULL,
HAVE_LICENCE NUMBER(1) NOT NULL,
AGE_GROUP VARCHAR2(3) NULL,
SPECIALITY VARCHAR2(100) NOT NULL,
COMMENT VARCHAR2(200) NULL,
CONSTRAINT USER_PK PRIMARY KEY (USER_ID)
);
Now I'd like to insert data in it, but it will only accept date which is 2000 or more and when it's less than 2000, for example '1998-13-07', it shows not a valid month.
INSERT INTO USER(USER_ID, FIRST_NAME, LAST_NAME, ID_CODE, DATE_OF_BIRTH, TRAINING_CLUB, HAVE_LICENCE, AGE_GROUP, SPECIALITY) VALUES (1, 'Mari', 'Mets', 4990713134, '1999-13-07', 'Erki Noole Athletics club', 1, 'U23', 'Sprint, hurdle race' );
INSERT INTO USER(USER_ID, FIRST_NAME, LAST_NAME, ID_CODE, DATE_OF_BIRTH, TRAINING_CLUB, HAVE_LICENCE, AGE_GROUP, SPECIALITY) VALUES (2, 'Meelis', 'Valgepea', 39704230213, '1997-23-04', 'Runningpartner', 1, 'M', 'Middle- ja long distance running');
INSERT INTO USER(USER_ID, FIRST_NAME, LAST_NAME, ID_CODE, DATE_OF_BIRTH, TRAINING_CLUB, HAVE_LICENCE, AGE_GROUP, SPECIALITY) VALUES (3, 'Karina', 'Justinov', 6020330872, '2002-30-03', 'SK Fortis', 1,'U20','Long and high jump');
INSERT INTO USER(USER_ID, FIRST_NAME, LAST_NAME, ID_CODE, DATE_OF_BIRTH, TRAINING_CLUB, HAVE_LICENCE, AGE_GROUP, SPECIALITY) VALUES (4, 'Lewis', 'Kordon', 38711120678, '1987-12-11', 'Niidupargi Athletics club', 1, 'M', 'Shot put');
INSERT INTO USER(USER_ID, FIRST_NAME, LAST_NAME, ID_CODE, DATE_OF_BIRTH, TRAINING_CLUB, HAVE_LICENCE, AGE_GROUP, SPECIALITY) VALUES (5, 'Getter', 'Tihhikov', 49802280417, '1998-28-02', 'Trainingpartner', 1, 'W','Long distance running');
INSERT INTO USER(USER_ID, FIRST_NAME, LAST_NAME, ID_CODE, DATE_OF_BIRTH, TRAINING_CLUB, HAVE_LICENCE, AGE_GROUP, SPECIALITY) VALUES (6, 'Andres', 'Allikvee', 50603212165, '2006-21-03', 'SK Lindon', 1, 'U16', 'Pole vault');
It shows that row 3 and 6 will be added and 1, 2, 4, 5 have not valid month.
create table users(
user_id integer not null,
date_of_birth timestamp not null
);
insert into users values (1, '1999-13-07');
-- ORA-01843: not a valid month
The problem is with the date literal. We are giving a literal string for a timestamp column, so how this is interpreted depends on database settings.
We can either explictly turn the strings to timestamps, providing the proper format specification:
into users values (1, to_timestamp('1999-13-07', 'YYYY-DD-MM'));
-- 1 rows affected
Or we can change the default timestamp format for our current session, so strings are correctly implicitly converted:
alter session set nls_timestamp_format = 'YYYY-DD-MM';
insert into users values (2, '1999-13-07');
-- 1 rows affected
Demo on DB Fiddle

INSERT ALL error ORA-02291 integrity constraint but PK is referenced

I'm creating a basic sales and inventory DB for a class.
I've successfully created the tables necessary with where I want my PK and FK's to be.
The issue I'm running into now is when I try to perform a multiple insert into my employees table.
Here's what has been created and inserted so far:
CREATE TABLE location (
zipcode int CONSTRAINT zipcode_pk PRIMARY KEY,
city varchar2 (50)
)
;
CREATE TABLE employees (
employeeid int CONSTRAINT employeeid_pk PRIMARY KEY,
firstname varchar2 (50),
lastname varchar2 (50),
street varchar2 (50),
state varchar2 (2),
zipcode int REFERENCES location (zipcode),
datehired date,
phonenum int,
salaryhr number
)
;
CREATE TABLE customer (
customerponum int CONSTRAINT customerponum_pk PRIMARY KEY,
firstname varchar2 (50),
lastname varchar2 (50),
street varchar2 (50),
zipcode int REFERENCES location (zipcode)
)
;
CREATE TABLE products (
productid int CONSTRAINT productid_pk PRIMARY KEY,
productname varchar2 (50),
price number (*,2),
costpercent int
)
;
CREATE TABLE inventory (
productid int REFERENCES products (productid),
unitonhand int,
CONSTRAINT productid_pkt PRIMARY KEY (productid)
)
;
CREATE TABLE sales (
ordernum int CONSTRAINT ordernum_pk PRIMARY KEY,
customerponum int REFERENCES customer (customerponum),
productid int REFERENCES products (productid),
employeeid int REFERENCES employees (employeeid),
saledate date,
unitssold int
)
;
INSERT ALL
INTO location (zipcode, city) VALUES (77095, 'Houston')
INTO location (zipcode, city) VALUES (77451, 'Dallas')
INTO location (zipcode, city) VALUES (77114, 'Austin')
INTO location (zipcode, city) VALUES (77369, 'Lubbock')
INTO location (zipcode, city) VALUES (75451, 'El Paso')
SELECT * FROM dual
;
INSERT ALL
INTO customer (customerponum, firstname, lastname, street, zipcode) VALUES (101, 'Josh', 'Smith', '100 Baker St',77095)
INTO customer (customerponum, firstname, lastname, street, zipcode) VALUES (102, 'John', 'Doe', '12 Yankee Ave',77451)
INTO customer (customerponum, firstname, lastname, street, zipcode) VALUES (103, 'Brandon', 'Markle', '1 Longhorn Blvd',77114)
INTO customer (customerponum, firstname, lastname, street, zipcode) VALUES (104, 'Mary', 'Eglin', '223 Aggie St',77369)
INTO customer (customerponum, firstname, lastname, street, zipcode) VALUES (105, 'Sue', 'Fields', '91 Patriot',75451)
SELECT * FROM dual
;
'''
---Oracle liveSQL this is the statement that I receive the error
---
INSERT ALL
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (1, 'Jason', 'Wayne', '103 Brown St', 'TX', 77453, '14-may-13', 2814441304, 13)
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (2, 'Jacob', 'Dutch', '14 Yawn Rd', 'TX', 77096, '12-july-11', 8325472222, 10)
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (3, 'Susan', 'Anthony', '1 Patronas Ln', 'TX', 77231, '08-jan-17', 2819993547, 9)
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (4, 'David', 'Lane', '888 Madrid Blvd', 'TX', 78113, '27-dec-18', 8321119876, 8)
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (5, 'Anthony', 'Barnard', '21 Adiom Cl', 'TX', 79448, '13-nov-17', 2814558008, 10)
SELECT * FROM dual
;
When I run the statement INSERT ALL INTO employees I get this error:
"ORA-02291: integrity constraint (SQL_NCBYEZZVAYRPDIJSWAZMSKRHK.SYS_C0016383126) violated - parent key not found ORA-06512: at "SYS.DBMS_SQL", line 1721"
The zip code values in your insert into the employees table don't match the ones you created in the location table, so the error is valid and expected.
Either change the employees zip codes to match the locations you already have, or more likely - since you already use those for customers - add new locations for the zip codes you are trying to use:
INSERT ALL
INTO location (zipcode, city) VALUES (77453, 'Lane City')
INTO location (zipcode, city) VALUES (77096, 'Houston')
INTO location (zipcode, city) VALUES (77231, 'Houston')
INTO location (zipcode, city) VALUES (78113, 'Falls City')
INTO location (zipcode, city) VALUES (79448, 'Richland')
SELECT * FROM dual
;
5 rows inserted.
INSERT ALL
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (1, 'Jason', 'Wayne', '103 Brown St', 'TX', 77453, '14-may-13', 2814441304, 13)
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (2, 'Jacob', 'Dutch', '14 Yawn Rd', 'TX', 77096, '12-july-11', 8325472222, 10)
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (3, 'Susan', 'Anthony', '1 Patronas Ln', 'TX', 77231, '08-jan-17', 2819993547, 9)
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (4, 'David', 'Lane', '888 Madrid Blvd', 'TX', 78113, '27-dec-18', 8321119876, 8)
INTO employees (employeeid, firstname, lastname, street, state, zipcode, datehired, phonenum, salaryhr) VALUES (5, 'Anthony', 'Barnard', '21 Adiom Cl', 'TX', 79448, '13-nov-17', 2814558008, 10)
SELECT * FROM dual
;
5 rows inserted.
db<>fiddle

Get value from table to use it in insert

I suppose this question was already asked somewhere here, but I have no idea how to name (and look for) it correctly.
The database:
CREATE TABLE department (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE employee (
id INTEGER PRIMARY KEY AUTOINCREMENT,
department_id INTEGER NOT NULL,
chief_id INTEGER,
name VARCHAR(100) NOT NULL UNIQUE,
salary INTEGER NOT NULL,
FOREIGN KEY (department_id) REFERENCES department (id),
FOREIGN KEY (chief_id) REFERENCES employee (id)
);
INSERT INTO department (name) VALUES ('sales'), ('it'), ('management');
INSERT INTO employee (department_id, chief_id, name, salary) VALUES
(3, NULL, 'Owner', 1000000),
(2, 1, 'Team manager', 9000),
(2, 3, 'Senior dev #1', 7000),
(2, 3, 'Senior dev #2', 7000);
Now in insert I should calculate chief_id on my own, but I'm curious if there is a possibility to get id by name, something like
SELECT id FROM employee WHERE name = 'Owner'
and use this value instead of hardcoded id in insert.
I've tried putting select statement instead of id but that does not work.
I am using SQLite.
You can do it with a subquery as yours, but the data has to be in the table before you can select it. Otherwise the subquery returns null. So you need to break the one INSERT into multiple INSERTs.
INSERT INTO employee (department_id, chief_id, name, salary) VALUES
(3, NULL, 'Owner', 1000000);
INSERT INTO employee (department_id, chief_id, name, salary) VALUES
(2, (SELECT id FROM employee WHERE name = 'Owner'), 'Team manager', 9000);
INSERT INTO employee (department_id, chief_id, name, salary) VALUES
(2, (SELECT id FROM employee WHERE name = 'Team manager'), 'Senior dev #1', 7000),
(2, (SELECT id FROM employee WHERE name = 'Team manager'), 'Senior dev #2', 7000);
But note, that the subquery must return only one row. So the column you're checking in it's WHERE clause must contain unique values. Usually a name is not unique, there are a lot of John Smith. Usually the ID is the unique identifier. So in a general inserting the ID directly is the right approach.

SQL Help(Date Functions)

I need help on SQL Queries.
TABLE:
Create Table Employees
( employee_id number(3) Primary Key,
first_name varchar2(10),
last_name varchar2(10),
dept_code varchar2(3),
hire_date date,
credit_limit number(4,2),
phone_ext varchar2(4),
manager_id number(3)
);
Entries:
insert into Employees values (201, 'Susan', 'Brown', 'Exe', To_Date('01-Jun-1998','DD-Mon-YYYY'), 30, '3484', null);
insert into Employees values (202, 'Jim', 'Kern', 'Sal', To_Date('16-Aug-1999','DD-Mon-YYYY'), 25, '8722', 201);
insert into Employees values (203, 'Martha', 'Woods', 'Shp', To_Date('02-Feb-2004','DD-Mon-YYYY'), 25, '7591', 201);
insert into Employees values (204, 'Ellen', 'Owens', 'Sal', To_Date('01-Jul-2003','DD-Mon-YYYY'), 15, '6830', 202);
I need a query to List all the employees, their hire dates and the number of days each person will have worked for the company as of January 1, 2007.
You can use YEAR() on a date field:
SELECT * FROM Employees WHERE YEAR(hire_date)='2003'
if it doesn't work, you can use EXTRACT():
SELECT * FROM Employees WHERE EXTRACT(YEAR FROM hire_date)='2003'
and, as Alan Hadsell rightly commented:
SELECT COUNT(*) FROM Employees WHERE EXTRACT(YEAR FROM hire_date)='2003'