As of version 10.4.3 of mariaDB bitemporal tables are supported natively by mariadb.
https://mariadb.com/kb/en/bitemporal-tables/
For an application, I want to create a bitemporal person database.
I have the following setup.
CREATE TABLE IF NOT EXISTS person
(
id INT UNSIGNED,
firstName VARCHAR(255),
lastName VARCHAR(255),
maritalStatus VARCHAR(255),
validFrom DATE NOT NULL,
validTo DATE NOT NULL,
systemFrom TIMESTAMP(6) AS ROW START INVISIBLE,
systemTo TIMESTAMP(6) AS ROW END INVISIBLE,
PERIOD FOR application_time(validFrom, validTo),
PERIOD FOR system_time(systemFrom, systemTo),
UNIQUE (id, application_time WITHOUT OVERLAPS)
)
WITH SYSTEM VERSIONING;
CREATE INDEX IF NOT EXISTS idx_validFrom ON person (validFrom);
CREATE INDEX IF NOT EXISTS idx_validTo ON person (validTo);
I am creating a bitemporal table person with an application_time which is the business timeline and a system_time which is the system time line. Both are defined as periods.
INSERT INTO zone.person (id,firstName, lastName, maritalStatus, validFrom, validTo)
VALUES (1,'John','Doe','married','2022-10-10','9999-12-31');
Here I am inserting a new Person who is married and this entry is valid from 2022-10-10 till the end of time.
UPDATE zone.person FOR PORTION OF application_time
FROM '2023-10-10' TO '9999-12-31'
SET maritalStatus = 'divorced'
WHERE id = 1;
Now the customer tells me that he will be divorced on '2023-10-10' so I updated the value from married to divorced with the timeframe.
SELECT * FROM person
WHERE '2023-10-10' BETWEEN person.validFrom AND person.validTo
If I query now the business state on '2023-10-10' the result is:
person
id
firstName
lastName
maritalStatus
validFrom
validTo
1
John
Doe
divorced
2023-10-10
9999-12-31
1
John
Doe
married
2022-10-10
2023-10-10
As you can see I get two values but from a business perspective, there could only be one valid maritalStatus at a specific time (date). I would expect one value here. We can see that on the future dated update the validToDate of the initial insert is terminated to the 2023-10-10. But in my opinion, this is wrong shouldn't it be terminated to the 2023-10-09?
Do I understand this implementation wrong or how can I setup mariadb to work this way?
Related
I want to assure at inserting a manager that department manager start date [DEPARTMENT.mgr_start_date] is coming after his birthdate [EMPLOYEE.bdate],
how can I do that?
CREATE TABLE IF NOT EXISTS EMPLOYEE
(
ssn INT(16) unsigned NOT NULL,
fname VARCHAR(16),
lname VARCHAR(16),
bdate DATE,
address VARCHAR(32),
gender enum('m','f'),
salary decimal(16,2),
Dno VARCHAR(8),
PRIMARY KEY (ssn)
);
CREATE TABLE IF NOT EXISTS DEPARTMENT
(
mgr_ssn INT(16) unsigned,
Dname VARCHAR(32),
mgr_start_date DATE,
Dnumber VARCHAR(8),
PRIMARY KEY (Dnumber),
FOREIGN KEY (mgr_ssn) REFERENCES EMPLOYEE(ssn)
);
You would have to do this with a trigger.
CHECK constraints can reference only columns in the table where the constraint is defined.
The full SQL standard includes a type of constraint called an ASSERTION, which allows multi-table constraints, but MariaDB does not implement this feature of SQL (very few brands of SQL databases do implement it).
CREATE TRIGGER t BEFORE INSERT ON DEPARTMENT
FOR EACH ROW BEGIN
IF NEW.mgr_start_date < (SELECT bdate FROM EMPLOYEE WHERE ssn = NEW.mgr_ssn) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'manager is way too young';
END IF;
END
Test:
insert into EMPLOYEE set ssn=123, bdate='2021-01-01';
insert into DEPARTMENT set mgr_ssn=123, dnumber='1', mgr_start_date='2010-01-01';
ERROR 1644 (45000): manager is way too young
I'm making a SQLite database where I want to have three tables: Users, Books and Bought. Users exists of the columns username, password, name, street, housenumber, postcode and country, where username is the primary key. Books exists of the columns ISBN, year, title, genre, price, author, publisher, summary, numberofpages and amountinstock, where ISBN and year are the primary key. And Bought exists of the columns username, ISBN, year, amount and time, where username, ISBN and year are foreign keys.
I want to add a trigger in such a way that when there will be added a tuple to Bought the SQL will check whether there's enough of that book in stock and if so then it will change the stock number of that book in Books and add the order to Bought.
I've tried already something, but it still gives me a syntax error around the when clauses, but I do not know why.
Here is the insert trigger that I made:
CREATE TRIGGER BoughtInStockTrigger
BEFORE INSERT ON Bought
FOR EACH ROW
WHEN (NEW.amount <= (SELECT SUM(amountinstock) FROM Books B WHERE B.ISBN = NEW.ISBN AND B.year = NEW.year))
BEGIN
UPDATE Books
SET amountinstock = amountinstock - NEW.amount
WHERE ISBN = NEW.ISBN AND year = NEW.year;
END
WHEN (NEW.amount > (SELECT SUM(amountinstock) FROM Books B WHERE B.ISBN = NEW.ISBN AND B.year = NEW.year))
BEGIN
ROLLBACK;
END;
Where did I make a syntax mistake?
I have a table Person with ID(Guid), FirstName(string), LastName(string) and 3000 entries. What I desperately need is the rank of a certain entry by ID in a sorted query by FirstName and LastName.
So for example: I search for any entries with FirstName or LastName containing the String 'mil' which returns 62 entries sorted. Since I know the ID of an entry somewhere in this result, I need the row_index of this entry.
I tried this with a Temp Table before, but since I'm working with sqlite-pcl for UWP I can't use 'CREATE TEMP TABLE' statements and so on, thus I need a solution in a single query.
PRAGMA temp_store = MEMORY;
DROP TABLE IF EXISTS TempQuery;
CREATE TEMP TABLE TempQuery AS SELECT ID FROM Person WHERE (Firstname LIKE '%mil%' OR LastName LIKE '%%');
SELECT rowid FROM TempQuery WHERE ID = '48a0231a-af41-450d-a291-5912d39119c9' LIMIT 1;
I have two tables for a hospital system
patient
(PK) ID - int (auto increments)
Name -varchar
surname -varchar
DOB - varchar
Email- varchar
Phone -varchar
(FK)address_ID
and
address table
Address(ID)-int (auto increment)
Line1 - varchar
Line2 - varchar
city - varchar
state - varchar
everytime I try and register a new patient, it doesn't include Address ID in the patient table. I have it address table and address_id linked to the patient table for address_ID in the database diagram as its foreign key, it keeps giving me an error saying its null. So if it doesn't automatically go in the patient table how do I auto increment it so that it stays the same as the address_ID in the address table?
This is the code I'm using to insert the values from the form.
string query1 = "insert into patient(name,surname,dob,email,phone) values (#pname, #psurname, #pdob, #pemail, #pphone)";
string query2 = "insert into patient_address(Line1,Line2,city,state) values (#pline1, #pline2, #pcity, #pstate)";
SqlCommand cmd1 = new SqlCommand(query1, con);
cmd1.Parameters.AddWithValue("#pname", pname.Text);
cmd1.Parameters.AddWithValue("#psurname", psurname.Text);
cmd1.Parameters.AddWithValue("#pdob", dob.SelectedValue);
cmd1.Parameters.AddWithValue("#pemail", pemail.Text);
cmd1.Parameters.AddWithValue("#pphone", pphone.Text);
SqlCommand cmd2 = new SqlCommand(query2, con);
cmd2.Parameters.AddWithValue("#pline1", pline1.Text);
cmd2.Parameters.AddWithValue("#pline2", pline2.Text);
cmd2.Parameters.AddWithValue("#pcity", pcity.Text);
cmd2.Parameters.AddWithValue("#cstate", pstate.SelectedValue);
con.Open();
cmd2.ExecuteNonQuery();
cmd1.ExecuteNonQuery();
con.Close();
If anyone could offer some kind of guidance it would be helpful! Thanks.
The address_ID is a (FK) can be Null or Not Null (you may check if it's allow to accept null or not (null-able or not), so check if (FK) accept to be null or not
In the 1:N relation:
If the (FK) is accept to be null some times, that mean some of patients here do not have an address (so it's not required).
But if the (FK) is not accept to be null, so all the patients should have an address, and it should not be null.
And the (PK) should not be null at all.
So in your case I think the simplest way to add a custom constraints
or add one extra column (IsAdressExist) to the patient table,
or simply first add an addition row in the address_table which will refer to (empty address with Address(ID)=-1 for example), then set the default value for the patients that do not have an address with (FK)address_ID =-1
or just set the Address(ID_FK) Default Value or Binding as a (NULL)
If you want to add a new address to the address table and you need to use the same new address to be FK to the patient table, so you need to (the simplest way):
1- Add the new address to the address table.
2- Get the MAX Address_ID (PK) from the address table
3- Use that max address_ID and insert it to the patient table as FK.
OR
You need to create one long query that will do the same previous steps that I mentioned above.
I want to create a dynamic database
with needed as step or flow on this basis..
how can i create database this by through store query or any other way.
I want to need a programmatically.
1)HEALTHY RECIPES CATEGORIES table
1)BreakFast
2)Lunch
3)Dinner
4)chicken & turkey
5)Dessert
...........
2) Breakfast table....
- orange and vanilla protein oatmeal
-chili-chocolote protein oatmeal
.....
3) - orange and vanilla protein oatmeal table
-Ingredients
-directions
Thanks All to in Advance...
I understand that you'd like to use SQLite. Run SQLite client (Sqliteman or similar), create a new database and run the below as a script:
create table category (
category_id integer not null primary key,
name varchar(80) not null
);
create table meal (
meal_id integer not null primary key,
name varchar(80) not null,
directions text
);
create table meal_category (
meal_category_id integer primary key,
meal_id integer not null references meal,
category_id integer not null references category
);
You can then insert data like this:
insert into category (category_id, name) values (1, 'Breakfast');
insert into category (category_id, name) values (2, 'Lunch');
insert into meal (meal_id, name) values (1, 'Orange and vanilla protein oatmeal');
insert into meal (meal_id, name) values (2, 'Chili-chocolote protein oatmeal');
insert into meal_category (meal_category_id, meal_id, category_id) values (1, 1, 1); -- meal 1 is a breakfast
insert into meal_category (meal_category_id, meal_id, category_id) values (2, 2, 1); -- meal 2 is a breakfast
And query it like this:
select m.name || ' is ' || c.name from meal m
join meal_category mc on m.meal_id = mc.meal_id
join category c on mc.category_id = c.category_id;
It's the simplest design. You may want to add additional fields and some indexes - please check tutorials on SQL how to do it. Anyway the above will give you a working SQLite database.
You may need table "ingredient" which will keep data of anything which can be used for a recipe (egg, flour, water etc) and "meal_ingredient" which will tell if an ingredient should be present in a meal. Text of the recipe can be kept in meal.recipe field.
Note that there are different ways to design a database and typically you should provide a detailed specification of the system which will use the database to have a good design.
It's best if you think what the database will be used for, what kind of data you want to get from it and then read on SQL and do some experiments on your own. For example, if you want to be able to look for any meal which uses flour, it's best to have ingredients in a separate table, linked to meal - just like a category is linked to a meal, it's called a "many to many relationship". But if you don't care about such a functionality, both recipe and a list of ingredients could be put in meal.recipe field. Design of the database should reflect your needs and the part of reality you want to have a model of.