SQL: view as function of value in table
-
28-10-2019 - |
Pergunta
I'm working with a transactional database: a relational database where a row in a table is defined as the set of values the database, at a given time, "thinks" the row's fields contain.
Part of the schema:
CREATE TABLE Article
(
id INTEGER,
PRIMARY KEY(id)
);
CREATE TABLE Article_headline
(
Article_id INTEGER,
headline TEXT,
tt DATETIME
FOREIGN KEY(Article_id) REFERENCES Article(id)
);
CREATE TABLE Article_body
(
Article_id INTEGER,
body TEXT,
tt DATETIME
FOREIGN KEY(Article_id) REFERENCES Article(id)
);
In other words, the virtual "Article" table has three columns: id, headline, and body.
I can create temporary views to represent the virtual "Article" table defined by a given time:
CREATE TEMPORARY VIEW Article_headline_old
AS SELECT Article_id, headline, MAX(tt)
FROM Article_headline
WHERE tt <= "2011-11-03 16:05:23"
GROUP BY Article_id;
CREATE TEMPORARY VIEW Article_body_old
AS SELECT Article_id, body, MAX(tt)
FROM Article_body
WHERE tt <= "2011-11-03 16:05:23"
GROUP BY Article_id;
CREATE TEMPORARY VIEW Article_old
AS SELECT id, headline, body
FROM Article, Article_headline_old, Article_body_old
WHERE Article_headline_old.Article_id = Article.id
AND Article_body_old.Article_id = Article.id;
I have to create these three temporary views each time I want to query the database to get an article, which I would rather not do. I would prefer to create permanent view "functions" as part of the schema itself:
CREATE VIEW Article_headline_at(theTime)
AS SELECT Article_id, headline, MAX(tt)
FROM Article_headline
WHERE tt <= theTime
GROUP BY Article_id;
CREATE VIEW Article_body_at(theTime)
AS SELECT Article_id, body, MAX(tt)
FROM Article_body
WHERE tt <= theTime
GROUP BY Article_id;
CREATE VIEW Article_at(theTime)
AS SELECT id, headline, body
FROM Article,
Article_headline_at(theTime) AS Article_headline_old,
Article_body_at(theTime) AS Article_body_old
WHERE Article_headline_old.Article_id = Article.id
AND Article_body_old.Article_id = Article.id;
And then when I want to select an article from the database:
SELECT * FROM Article_at("2011-11-03 16:05:23");
Does SQL have any similar functionality?
Solução
You could create three stored procedures and pass theTime as a variable to each.
For Article_headline_at and Article_body_old_at insert these stored procedures into a temporary table inside Article_at stored procedures and do the query. This could be your solution:
CREATE PROCEDURE Article_headline_at @theTime datetime as
SELECT Article_id, headline, MAX(tt)
FROM Article_headline
WHERE tt <= theTime
GROUP BY Article_id;
-----
CREATE PROCEDURE Article_body_old_at @theTime datetime as
SELECT Article_id, body, MAX(tt)
FROM Article_body
WHERE tt <= theTime
GROUP BY Article_id;
-----
CREATE PROCEDURE Article_at @theTime datetime as
IF OBJECT_ID('tempdb.dbo.#Article_headline_at') IS NOT NULL DROP TABLE tempdb.dbo.#Article_headline_at
IF OBJECT_ID('tempdb.dbo.#Article_body_old_at') IS NOT NULL DROP TABLE tempdb.dbo.#Article_body_old_at
create table #Article_headline_at (
Article_id int,
body nvarchar(max),
tt int
)
create table #Article_body_old_at (
Article_id int,
headline nvarchar(max),
tt int
)
declare @sql1 nvarchar(max)
declare @sql2 nvarchar(max)
set @sql1 = 'insert into #Article_headline_at exec #Article_headline_at @theTime = '''+ @theTime + ''''
set @sql2 = 'insert into #Article_body_old_at exec #Article_body_old_at @theTime = '''+ @theTime + ''''
exec sp_executesql @sql1
exec sp_executesql @sql2
SELECT id, headline, body
FROM Article, #Article_headline_at(theTime), #Article_body_at(theTime)
WHERE #Article_headline_old.Article_id = Article.id
AND #Article_body_old.Article_id = Article.id;
-----
so at the end of it all you can do
exec Article_at @theTime = "2011-11-03 16:05:23"
but I am sure there is a easier way around but this the only way I can think of.