I have created the view with some constraints in Oracle 12c. But when I insert values which violate the constraint also be able to insert from the view. It seems like a loophole.
--Create view Emp_1
CREATE VIEW Emp_1
AS
SELECT Empid, Ename, Salary
FROM employees
WHERE salary < 25000
This view is to show only employees who are having less than 25000 for salary.
But when I insert employee who have more than 25000 as salary, View allows me to insert(this is incorrect). but it doesn't appear when i query the view(this is correct)
Is this as design or what do i can do to overcome this?
Technically this is a insert-able view. so it allows to insert. But conceptually user can see only employees who have salary less than 25000. So it does not allow to insert more than the condition.
Please correct me if I am wrong and please help.
Friends thanks for the help. I found it now.
You can use WITH CHECK OPTION CONSTRAINT to over come this.
CREATE VIEW Emp_2
AS
SELECT Empid, Date_Joined, Salary
FROM employees
WHERE salary < 25000
WITH CHECK OPTION CONSTRAINT Emp_2_Salary_Constraint;
Then it shows this error when you are violating it.
SQL Error: ORA-01402: view WITH CHECK OPTION where-clause violation
You will have to add the constraint on the employees table. A view is just a representation of the query. It does not have an assigned storage, and since the underlying table do not have any such constraint, you are able to insert that data. So the design and output is as it should be.
Related
I am trying to create a VPD in Oracle using SQL statements. The purpose of this problem is so an employee could ONLY view records for employees in the same department while masking their coworker's salaries as NULL.
The code for the table being used is as follows
create table Employee
(
ID number primary key,
DEPT varchar2(25),
SALARY number(8,2),
NAME varchar2(25)
);
I am unsure what the best way to go about doing this would be.... would it be to create a package and use an application context. I believe getting the table to only display those in same "DEPT" I understand but unsure how to mask the data of those with same DEPT but different ID.
Native RLS will get you close but not totally there. Using "sec_relevant_cols" will give you the option between
only seeing the rows that match your predicate, but all values are present
seeing all the rows, but masking values that do not match your predicate
whereas (if I'm reading correctly) you want to see only predicate matching rows AND mask out some values as well.
You could achieve this with a two-step method
Your context contains two keys (say) DEPT and YOUR_ID
The RLS policy is "where dept = sys_context(ctx,'DEPT')"
You have a view EMP to which that policy is applied, being
select
id,
dept,
name,
case when id = sys_context(ctx,'YOUR_ID') then sal else null end sal
from EMP_TABLE
let's assume we have a Relational DB in MS-Access(image).
Where We have 4 Tables and columns related to tables which are related to one another.
I know we can insert like:
INSERT INTO Project ( ProjectName, ProjectID, FK_Employee, FK_Department )
SELECT 'Project1' AS Name, '99950' AS ID, Employee.ID, Department.ID
FROM Department, Employee
WHERE (((Employee.employeeName)=#employee) AND ((Department.DepartmentName)=#Dept));
But is there any better way to do it? I know we can Select with different types of Join. Is it make sense or is there a way to use Join with insertion?
I've faced a problem with this kind of query when the Foreign key is optional. What I mean is if I use this query for my VB/ADO.Net and if I send DBNull.Value it creates no new row or
In precise.
Let's say I have saved no employee during project creation. So, my FK_Employee is Empty. Now, I want to insert a new Employee in the Employee table and also update the Foreign Key in Project table where ProjectName is 'Project1'. Is it possible to do it in one query? If it is not, how can I insert values in Employee Table and then read the Auto incremented ID and update it to Project Table in VB/ADO.Net? (Answer with C# is also okay).
I really am stuck here. If anyone knows the answer please help me to get rid of this situation. I really appreciate your kindness and help. Thank you in advance.
I accidentally deleted a table called DEPARTMENT from my oracle database and I want to restore it back. So I googled and found the solution.
Here is what I did:
SHOW RECYCLEBIN;
CRIMINALS BIN$hqnw1JViXO/gUwPAcgqn3A==$0 TABLE 2019-04-16:13:17:16
DEPARTMENT BIN$hqnw1JVjXO/gUwPAcgqn3A==$0 TABLE 2019-04-16:13:19:04
DEPARTMENT BIN$hqnw1JVkXO/gUwPAcgqn3A==$0 TABLE 2019-04-16:13:21:23
DEPARTMENT BIN$hqnw1JVnXO/gUwPAcgqn3A==$0 TABLE 2019-04-16:13:36:34
FLASHBACK table department TO BEFORE DROP;
Flashback succeeded.
If you can see the SHOW RECYCLEBIN QUERY, You can tell there are more than one department table and all of them have different content. My Question is how can I get the content of all 3 table in one.
After flashback, rename each DEPARTMENT table to a new name, e.g.
rename department to dept_1;
Do it for all of them but the last one (whose name will remain DEPARTMENT). Then insert the rest of data into it:
insert into department
select * from dept_1
union all
select * from dept_2;
Note that uniqueness might be violated; if table's description has changed, select * might not work (so you'll have to name all columns, one-by-one).
But, generally speaking, that's the idea of how to do it.
I have the following 3 tables:
employees
departments
employees_departments (join table between employees and departments with additional info)
The department also has a column manager_id which is a foreign key to the employees table (a department has a manager from the employees table).
I have a requirement in which I must place a constraint in which no employee under a manager can have a higher salary than the manager.
My attempt at solving this:
ALTER TABLE employees
ADD CONSTRAINT check_salary
CHECK (salary > (SELECT salary
FROM employees e2
INNER JOIN employees_departments ed2 ON e2.id_employee = ed2.id_employee
INNER JOIN departments d2 ON d2.id_department = ed2.id_department
WHERE e2.id_employee != manager_id (but how do I get the manager id)
AND d2.id_departament = manager_department_id (again don't know how to do get it)
)
I get an error that subqueries are not allowed. Is this even possible to do in a constraint? How can it be modeled in a normal query?
I must also add that I have close to none experience with SQL Server and very little with SQL in general.
Any help greatly appreciated!
Even if you could do this, what would you expect to happen when the data changes such that for some rows the constraint fails (like a manager gets a salary reduction)? Sounds like this might be a bad problem/business rule description.
If it's purely an insert/update time check then use code or (yuk) a trigger.
Another alternative might be to use an updatable view which only selects employees that earn below their manager (i.e. everyone). By updating and inserting there you might be able to make it work in every case because if the insert/update into the view would not satisfy the view's criteria it will reject it.
Read up on the view and specifically the WITH CHECK OPTION.
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql
I'm creating 2 test tables in my oracle 10g database: STAFFS and DEPARTMENTS. Neither table has any primary keys, constraints, joins or any other thing since I don't know any of those anyway. Both are just plain tables with their fields.
In DEPARTMENTS, I have 2 fields: DEPT_NAME and DEPT_CODE. This table will serve as a reference table.
In STAFFS, I have 4 fields: STAFF_ID, STAFF_NAME, DEPT_NAME, and DEPT_CODE.
Say I change the DEPT_NAME of a staff record, how do I make the DEPT_CODE for that staff also change? I've tried creating triggers but all I get is either some mutating error thing or some recursive have been reach error.
Simple solution.
Remove DEPT_NAME column from STAFFS table.
JOIN DEPARTMENTS table using DEPT_CODE when ever you want to do so
This is called normalisation