How to Set a Parent Tables Updated Value in Materialized View Table with a Trigger if the Updated Value was not Null or Empty - sql-update

I am using C#'s EF Core and a nice benefit of it is how I can dynamically update any attribute in the Users model with one method. I want to make a trigger to sense when my token attribute in my table Users is updated. That's pretty easy but, lets say Users have two 'sub-classes/materialized views' Donators and Staffs. I want those following symmetrical attributes to match up when they are updated through a trigger.
CREATE TABLE [Users](
email VARCHAR(320) NOT NULL,
password_salt varbinary(max) NOT NULL,
password_hash varbinary(max) NOT NULL,
token VARCHAR(320),
/*d=Donator | s=Staff*/
roles VARCHAR (2) NOT NULL,
/*For: Donator */
amount_donated MONEY,
/*For: Staff */
title VARCHAR(128),
PRIMARY KEY (email),
);
/***Role Based Sub-Class Tables***/
CREATE TABLE Donators(
email VARCHAR(320) NOT NULL,
password_salt varbinary(max) NOT NULL,
password_hash varbinary(max) NOT NULL,
token VARCHAR(320),
roles VARCHAR (2) NOT NULL,
amount_donated MONEY NOT NULL,
PRIMARY KEY (email),
FOREIGN KEY (email) REFERENCES [Users](email)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE Staffs(
email VARCHAR(320) NOT NULL,
password_salt varbinary(max) NOT NULL,
password_hash varbinary(max) NOT NULL,
token VARCHAR(320),
roles VARCHAR (2) NOT NULL,
title VARCHAR(128) NOT NULL,
type VARCHAR(256),
created DATETIME,
PRIMARY KEY (email),
FOREIGN KEY (email) REFERENCES [Users](email)
ON DELETE CASCADE
ON UPDATE CASCADE
);
To reframe from cluttering this question section I will not put my trigger since it does not work how I want at the moment because Donators attribute token does not match up when I update the Users attribute token.
My Code pertaining to this question can be found here (lines 248-366). Heads up Users have a few more subclasses. But, I just need to understand and find the code that allows token in Staffs and Donators.

Ok, so a Ravenous Baboon's article is where I found the answer to my question. Here is a trigger of how I am going to keep my materialized view Donators up to date. Following along for any more inheritance I think is self-explanatory. (Feel free to ask if confused)
CREATE TRIGGER User_Updated_Check
ON [Users]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE #email VARCHAR(320);
DECLARE #old_roles VARCHAR (2);
DECLARE #new_password_hash VARBINARY(max);
DECLARE #new_password_salt VARBINARY(max);
DECLARE #new_token VARCHAR(320);
DECLARE #new_f_name VARCHAR(64);
DECLARE #new_l_name VARCHAR(64);
DECLARE #new_roles VARCHAR (2);
DECLARE #new_amount_donated MONEY;
DECLARE #new_title VARCHAR(128);
DECLARE #new_type VARCHAR(256);
DECLARE #new_created DATETIME;
SET #email = (SELECT email FROM Inserted);
SET #old_roles = (SELECT roles FROM Deleted);
SET #new_password_hash = (SELECT password_hash FROM Inserted);
SET #new_password_salt = (SELECT password_salt FROM Inserted);
SET #new_token = (SELECT token FROM Inserted);
SET #new_f_name = (SELECT f_name FROM Inserted);
SET #new_l_name = (SELECT l_name FROM Inserted);
SET #new_roles = (SELECT roles FROM Inserted);
SET #new_amount_donated = (SELECT amount_donated FROM Inserted);
SET #new_title = (SELECT title FROM Inserted);
SET #new_type = (SELECT type FROM Inserted);
SET #new_created = (SELECT created FROM Inserted);
IF #old_roles != #new_roles
BEGIN
THROW 51000, 'The Roles need to match and cannot change', 1;
ROLLBACK TRANSACTION
END
IF #new_roles != 'd' AND
#new_roles != 's' AND
#new_roles != 'e' AND
#new_roles != 'a' AND
#new_roles != 'sd' AND
#new_roles != 'ed' AND
#new_roles != 'ad'
BEGIN
THROW 51000, 'The Role entered does not exist', 1;
ROLLBACK TRANSACTION
END
-- Donators
IF #new_roles = 'd' OR
#new_roles = 'sd' OR
#new_roles = 'ed' OR
#new_roles = 'ad'
IF UPDATE(token)
UPDATE Donators
SET token = #new_token
WHERE email = #email;
IF Update(password_salt)
UPDATE Donators
SET password_salt = #new_password_salt
WHERE email = #email;
IF Update(password_hash)
UPDATE Donators
SET password_hash = #new_password_hash
WHERE email = #email;
IF UPDATE(f_name)
UPDATE Donators
SET f_name = #new_f_name
WHERE email = #email;
IF Update(l_name)
UPDATE Donators
SET l_name = #new_l_name
WHERE email = #email;
IF Update(amount_donated)
UPDATE Donators
SET amount_donated = #new_amount_donated
WHERE email = #email;
END

Related

How do I create composite key using loopback4?

CREATE TABLE dbo.Users (
id int NOT NULL IDENTITY(1,1),
uid int NOT NULL,
username nvarchar(65) NULL,
password varchar(100) NULL,
firstname nvarchar(50) NULL,
lastname nvarchar(50) NULL,
);
ALTER TABLE dbo.Users ADD CONSTRAINT PK_Users PRIMARY KEY (id, uid);
This is my sql query and want to create data model for this schema using loopback4.
Unfortunately, it doesn't seem that this feature is currently supported. An open issue tracking this feature can be found on their GitHub page here.

How get Region ID or Region Name in Oracle Apex 5

I want to implement Authorization Scheme using my own created tables,for this purpose I want to get Current Region Name ,how to get it?
First, you'll need to assign a static id to your region.. then you can query the apex_application_page_regions table.
SELECT region_name
FROM apex_application_page_regions
WHERE static_id = 'SOME_STATIC_ID'
AND page_id = :APP_PAGE_ID
AND application_id = :APP_ID;
You don't actually need to assign a static ID for this purpose. There is a column REGION_ID in the apex_application_page_regions table. So filter out that column based on REGION_NAME.
select region_id from apex_application_page_regions
where region_name = 'your_region_name';
You can easily turn this into a function for future use:
function get_region_id (p_app_id number, p_app_page_id number, p_ir_static_id varchar2) return number is
l_region_id number;
begin
select region_id into l_region_id
from apex_application_page_regions
where application_id = p_app_id
and page_id = p_app_page_id
and upper(static_id) = upper(p_ir_static_id)
and upper(template) = upper('Interactive Report');
return l_region_id;
end get_region_id;

Trigger after insert with condition in oracle

I have an error with my trigger. it show
LINE/COL ERROR
-------- --------------------------------------------
2/2 PL/SQL: SQL Statement ignored
2/6 PL/SQL: ORA-00922: missing or invalid option
I want this trigger run if the customertype is member.
Here are my table
TABLE CUSTOMER
CREATE TABLE CUSTOMER
(CUSTOMERID VARCHAR2(100) primary key,
CUSTOMERNAME VARCHAR2(50),
CUSTOMERADDRESS VARCHAR2(100),
CUSTOMERPHONE VARCHAR2(15),
CUSTOMEREMAIL VARCHAR2(50),
CUSTOMERTYPE VARCHAR2(15)
)
TABLE MEMBER
CREATE TABLE MEMBER
(MEMBERID VARCHAR2(100),
USERNAME VARCHAR2(25),
PASSWORD VARCHAR2(10),
CUSTOMERID VARCHAR2(100),
CONSTRAINT FK_Member Foreign Key (CustomerId)
REFERENCES Customer(CustomerId)
);
This is my trigger
CREATE or replace TRIGGER insertMember
after insert ON CUSTOMER
for each row
BEGIN
SET NOCOUNT ON
If (select customertype from customer) = 'member'
begin
INSERT INTO MEMBER (customerid ) values
(:new.customerid);
END insertMember;
/

Understanding Secondary Indexes

if i have Table
Table
CREATE TABLE Users (
userId STRING(36) NOT NULL,
contactName STRING(300) NOT NULL,
eMail STRING(100) NOT NULL,
....
) PRIMARY KEY (userId)
and secondary index
CREATE NULL_FILTERED INDEX ActiveUsersByEMail
ON Users (
eMail,
isActive,
)
and i select record by:
SELECT * FROM Users WHERE eMail = 'test#test.com' AND isActive = TRUE
spanner will automatically look at index, take userId and give me a record ?.
or i need to create
CREATE NULL_FILTERED INDEX ActiveUsersByEMail_01
ON Users (
eMail,
isActive,
userId
)
and first take userId by:
SELECT userId from Users#{FORCE_INDEX=ActiveUsersByEMail_01} WHERE eMail = 'test#test.com' AND isActive = TRUE
and then i take a record by:
`SELECT * FROM Users WHERE userId = '${userId}'``
Question is automatically use or not spanner secondary indices for standard select if condition match secondary index keys?
You should use FORCE_INDEX as Cloud Spanner will only choose an index in rare circumstances as stated here. You can use the STORING clause to add data directly to the index, allowing you to read the data directly from the index to avoid the second call. This is suggested for common query patterns in your application.
In github i ask same question and It turned out that this is easily done (without creating additional index) by:
SELECT * from Users#{FORCE_INDEX=ActiveUsersByEMail} WHERE eMail = 'test#test.com' AND isActive = TRUE
At this time the search is going on index and row come with all fields

Complex SQL syntax

I have a game, and in the database I'm saving the user actions by date & time.
CREATE TABLE user_actions
(
aId BIGSERIAL PRIMARY KEY NOT NULL,
userId BIGINT NOT NULL REFERENCES users(uId) DEFERRABLE INITIALLY DEFERRED,
aDate TIMESTAMP without time zone DEFAULT now(),
aType INTEGER NOT NULL DEFAULT 0
);
My users are identified with email
CREATE TABLE users(
uId BIGSERIAL PRIMARY KEY NOT NULL,
uName VARCHAR (50) NOT NULL,
uEmail VARCHAR (75) UNIQUE NULL
);
and each day new prizes are added each day has a different number of prizes
CREATE TABLE prizes(
pId BIGSERIAL PRIMARY KEY NOT NULL,
pDate TIMESTAMP without time zone DEFAULT now(),
pType INTEGER NULL
pSize INTEGER NULL
);
This query list the userId and his last action date, per user
select distinct userId, max(aDate) from user_actions GROUP BY userId order by userId;
I want to create a query that will count the number of prizes added since each user last action.
I'm running:
OS: Debian
DB: Postgresql
code: Django
I think I will use CTE though It has not been tested
WITH last_actions AS (
SELECT DISTINCT userId, MAX(aDate) as last_logged
FROM user_actions
GROUP BY userId ORDER BY userId)
SELECT a.userId, COUNT(b.pDate)
FROM last_actions a, prizes b
WHERE b.pDate >= a.last_logged
GROUP BY a.userId;