ఫంక్షనల్ DBMS

డేటాబేస్‌ల ప్రపంచం చాలా కాలంగా SQL భాషను ఉపయోగించే రిలేషనల్ DBMSలచే ఆధిపత్యం చెలాయిస్తోంది. ఎంతగా అంటే ఉద్భవిస్తున్న వేరియంట్‌లను NoSQL అంటారు. వారు ఈ మార్కెట్‌లో తమ కోసం ఒక నిర్దిష్ట స్థానాన్ని ఏర్పరచుకోగలిగారు, కానీ సంబంధిత DBMSలు చనిపోవు మరియు వాటి ప్రయోజనాల కోసం చురుకుగా ఉపయోగించడం కొనసాగుతుంది.

ఈ వ్యాసంలో నేను ఫంక్షనల్ డేటాబేస్ భావనను వివరించాలనుకుంటున్నాను. మెరుగైన అవగాహన కోసం, నేను దీన్ని క్లాసికల్ రిలేషనల్ మోడల్‌తో పోల్చడం ద్వారా చేస్తాను. ఇంటర్నెట్‌లో కనుగొనబడిన వివిధ SQL పరీక్షల నుండి సమస్యలు ఉదాహరణలుగా ఉపయోగించబడతాయి.

పరిచయం

రిలేషనల్ డేటాబేస్‌లు టేబుల్‌లు మరియు ఫీల్డ్‌లపై పనిచేస్తాయి. ఫంక్షనల్ డేటాబేస్లో, తరగతులు మరియు విధులు వరుసగా ఉపయోగించబడతాయి. N కీలతో కూడిన పట్టికలోని ఫీల్డ్ N పారామితుల ఫంక్షన్‌గా సూచించబడుతుంది. పట్టికల మధ్య సంబంధాలకు బదులుగా, కనెక్షన్ చేయబడిన తరగతిలోని వస్తువులను తిరిగి ఇచ్చే విధులు ఉపయోగించబడతాయి. JOINకి బదులుగా ఫంక్షన్ కూర్పు ఉపయోగించబడుతుంది.

నేరుగా టాస్క్‌లకు వెళ్లే ముందు, నేను డొమైన్ లాజిక్ టాస్క్‌ను వివరిస్తాను. DDL కోసం నేను PostgreSQL సింటాక్స్‌ని ఉపయోగిస్తాను. ఫంక్షనల్ కోసం దాని స్వంత సింటాక్స్ ఉంది.

పట్టికలు మరియు ఫీల్డ్‌లు

పేరు మరియు ధర ఫీల్డ్‌లతో కూడిన సాధారణ Sku వస్తువు:

రిలేషనల్

CREATE TABLE Sku
(
    id bigint NOT NULL,
    name character varying(100),
    price numeric(10,5),
    CONSTRAINT id_pkey PRIMARY KEY (id)
)

ఫంక్షనల్

CLASS Sku;
name = DATA STRING[100] (Sku);
price = DATA NUMERIC[10,5] (Sku);

మేము రెండు ప్రకటిస్తాము విధులు, ఇది ఒక పరామితి Skuని ఇన్‌పుట్‌గా తీసుకుంటుంది మరియు ఆదిమ రకాన్ని అందిస్తుంది.

ఫంక్షనల్ DBMSలో ప్రతి ఆబ్జెక్ట్ స్వయంచాలకంగా రూపొందించబడే కొన్ని అంతర్గత కోడ్‌ను కలిగి ఉంటుందని మరియు అవసరమైతే యాక్సెస్ చేయగలదని భావించబడుతుంది.

ఉత్పత్తి/స్టోర్/సరఫరాదారు కోసం ధరను సెట్ చేద్దాం. ఇది కాలానుగుణంగా మారవచ్చు, కాబట్టి టేబుల్‌కి టైమ్ ఫీల్డ్‌ని జోడిద్దాం. కోడ్‌ను తగ్గించడానికి రిలేషనల్ డేటాబేస్‌లోని డైరెక్టరీల కోసం పట్టికలను ప్రకటించడాన్ని నేను దాటవేస్తాను:

రిలేషనల్

CREATE TABLE prices
(
    skuId bigint NOT NULL,
    storeId bigint NOT NULL,
    supplierId bigint NOT NULL,
    dateTime timestamp without time zone,
    price numeric(10,5),
    CONSTRAINT prices_pkey PRIMARY KEY (skuId, storeId, supplierId)
)

ఫంక్షనల్

CLASS Sku;
CLASS Store;
CLASS Supplier;
dateTime = DATA DATETIME (Sku, Store, Supplier);
price = DATA NUMERIC[10,5] (Sku, Store, Supplier);

సూచికలు

చివరి ఉదాహరణ కోసం, మేము అన్ని కీలు మరియు తేదీపై సూచికను నిర్మిస్తాము, తద్వారా మేము నిర్దిష్ట సమయానికి ధరను త్వరగా కనుగొనగలము.

రిలేషనల్

CREATE INDEX prices_date
    ON prices
    (skuId, storeId, supplierId, dateTime)

ఫంక్షనల్

INDEX Sku sk, Store st, Supplier sp, dateTime(sk, st, sp);

పనులు

సంబంధిత నుండి తీసుకున్న సాపేక్షంగా సాధారణ సమస్యలతో ప్రారంభిద్దాం వ్యాసాలు Habr న.

ముందుగా, డొమైన్ లాజిక్‌ను డిక్లేర్ చేద్దాం (సంబంధిత డేటాబేస్ కోసం ఇది నేరుగా పై కథనంలో చేయబడుతుంది).

CLASS Department;
name = DATA STRING[100] (Department);

CLASS Employee;
department = DATA Department (Employee);
chief = DATA Employee (Employee);
name = DATA STRING[100] (Employee);
salary = DATA NUMERIC[14,2] (Employee);

టాస్క్ 1.1

వారి తక్షణ సూపర్‌వైజర్ కంటే ఎక్కువ జీతం పొందే ఉద్యోగుల జాబితాను ప్రదర్శించండి.

రిలేషనల్

select a.*
from   employee a, employee b
where  b.id = a.chief_id
and    a.salary > b.salary

ఫంక్షనల్

SELECT name(Employee a) WHERE salary(a) > salary(chief(a));

టాస్క్ 1.2

వారి డిపార్ట్‌మెంట్‌లో గరిష్ట జీతం పొందే ఉద్యోగులను జాబితా చేయండి

రిలేషనల్

select a.*
from   employee a
where  a.salary = ( select max(salary) from employee b
                    where  b.department_id = a.department_id )

ఫంక్షనల్

maxSalary 'Максимальная зарплата' (Department s) = 
    GROUP MAX salary(Employee e) IF department(e) = s;
SELECT name(Employee a) WHERE salary(a) = maxSalary(department(a));

// или если "заинлайнить"
SELECT name(Employee a) WHERE 
    salary(a) = maxSalary(GROUP MAX salary(Employee e) IF department(e) = department(a));

రెండు అమలులు సమానమైనవి. మొదటి సందర్భంలో, రిలేషనల్ డేటాబేస్‌లో మీరు క్రియేట్ వ్యూని ఉపయోగించవచ్చు, అదే విధంగా మొదట దానిలోని నిర్దిష్ట విభాగానికి గరిష్ట జీతం లెక్కించబడుతుంది. కింది వాటిలో, స్పష్టత కోసం, నేను మొదటి కేసును ఉపయోగిస్తాను, ఎందుకంటే ఇది పరిష్కారాన్ని బాగా ప్రతిబింబిస్తుంది.

టాస్క్ 1.3

డిపార్ట్‌మెంట్ IDల జాబితాను ప్రదర్శించండి, 3 మంది వ్యక్తులకు మించని ఉద్యోగుల సంఖ్య.

రిలేషనల్

select department_id
from   employee
group  by department_id
having count(*) <= 3

ఫంక్షనల్

countEmployees 'Количество сотрудников' (Department d) = 
    GROUP SUM 1 IF department(Employee e) = d;
SELECT Department d WHERE countEmployees(d) <= 3;

టాస్క్ 1.4

అదే విభాగంలో పనిచేస్తున్న నిర్ణీత మేనేజర్ లేని ఉద్యోగుల జాబితాను ప్రదర్శించండి.

రిలేషనల్

select a.*
from   employee a
left   join employee b on (b.id = a.chief_id and b.department_id = a.department_id)
where  b.id is null

ఫంక్షనల్

SELECT name(Employee a) WHERE NOT (department(chief(a)) = department(a));

టాస్క్ 1.5

గరిష్ట మొత్తం ఉద్యోగి జీతంతో డిపార్ట్‌మెంట్ IDల జాబితాను కనుగొనండి.

రిలేషనల్

with sum_salary as
  ( select department_id, sum(salary) salary
    from   employee
    group  by department_id )
select department_id
from   sum_salary a       
where  a.salary = ( select max(salary) from sum_salary )

ఫంక్షనల్

salarySum 'Максимальная зарплата' (Department d) = 
    GROUP SUM salary(Employee e) IF department(e) = d;
maxSalarySum 'Максимальная зарплата отделов' () = 
    GROUP MAX salarySum(Department d);
SELECT Department d WHERE salarySum(d) = maxSalarySum();

మరొకదాని నుండి మరింత క్లిష్టమైన పనులకు వెళ్దాం వ్యాసాలు. ఇది MS SQLలో ఈ టాస్క్‌ను ఎలా అమలు చేయాలనే వివరణాత్మక విశ్లేషణను కలిగి ఉంది.

టాస్క్ 2.1

1997లో ఏ విక్రేతలు 30 యూనిట్ల కంటే ఎక్కువ ఉత్పత్తి నంబర్ 1ని విక్రయించారు?

డొమైన్ లాజిక్ (RDBMSలో మునుపటిలా మేము డిక్లరేషన్‌ను దాటవేస్తాము):

CLASS Employee 'Продавец';
lastName 'Фамилия' = DATA STRING[100] (Employee);

CLASS Product 'Продукт';
id = DATA INTEGER (Product);
name = DATA STRING[100] (Product);

CLASS Order 'Заказ';
date = DATA DATE (Order);
employee = DATA Employee (Order);

CLASS Detail 'Строка заказа';

order = DATA Order (Detail);
product = DATA Product (Detail);
quantity = DATA NUMERIC[10,5] (Detail);

రిలేషనల్

select LastName
from Employees as e
where (
  select sum(od.Quantity)
  from [Order Details] as od
  where od.ProductID = 1 and od.OrderID in (
    select o.OrderID
    from Orders as o
    where year(o.OrderDate) = 1997 and e.EmployeeID = o.EmployeeID)
) > 30

ఫంక్షనల్

sold (Employee e, INTEGER productId, INTEGER year) = 
    GROUP SUM quantity(OrderDetail d) IF 
        employee(order(d)) = e AND 
        id(product(d)) = productId AND 
        extractYear(date(order(d))) = year;
SELECT lastName(Employee e) WHERE sold(e, 1, 1997) > 30;

టాస్క్ 2.2

ప్రతి కొనుగోలుదారు (పేరు, ఇంటిపేరు), 1997లో కొనుగోలుదారు అత్యధికంగా డబ్బు ఖర్చు చేసిన రెండు వస్తువులను (పేరు) కనుగొనండి.

మేము మునుపటి ఉదాహరణ నుండి డొమైన్ లాజిక్‌ను విస్తరిస్తాము:

CLASS Customer 'Клиент';
contactName 'ФИО' = DATA STRING[100] (Customer);

customer = DATA Customer (Order);

unitPrice = DATA NUMERIC[14,2] (Detail);
discount = DATA NUMERIC[6,2] (Detail);

రిలేషనల్

SELECT ContactName, ProductName FROM (
SELECT c.ContactName, p.ProductName
, ROW_NUMBER() OVER (
    PARTITION BY c.ContactName
    ORDER BY SUM(od.Quantity * od.UnitPrice * (1 - od.Discount)) DESC
) AS RatingByAmt
FROM Customers c
JOIN Orders o ON o.CustomerID = c.CustomerID
JOIN [Order Details] od ON od.OrderID = o.OrderID
JOIN Products p ON p.ProductID = od.ProductID
WHERE YEAR(o.OrderDate) = 1997
GROUP BY c.ContactName, p.ProductName
) t
WHERE RatingByAmt < 3

ఫంక్షనల్

sum (Detail d) = quantity(d) * unitPrice(d) * (1 - discount(d));
bought 'Купил' (Customer c, Product p, INTEGER y) = 
    GROUP SUM sum(Detail d) IF 
        customer(order(d)) = c AND 
        product(d) = p AND 
        extractYear(date(order(d))) = y;
rating 'Рейтинг' (Customer c, Product p, INTEGER y) = 
    PARTITION SUM 1 ORDER DESC bought(c, p, y), p BY c, y;
SELECT contactName(Customer c), name(Product p) WHERE rating(c, p, 1997) < 3;

విభజన ఆపరేటర్ కింది సూత్రంపై పని చేస్తుంది: ఇది SUM (ఇక్కడ 1), పేర్కొన్న సమూహాలలో (ఇక్కడ కస్టమర్ మరియు సంవత్సరం, కానీ ఏదైనా వ్యక్తీకరణ కావచ్చు), ఆర్డర్‌లో పేర్కొన్న వ్యక్తీకరణల ద్వారా సమూహాలలో క్రమబద్ధీకరించబడిన తర్వాత పేర్కొన్న వ్యక్తీకరణను సంగ్రహిస్తుంది ( ఇక్కడ కొనుగోలు చేయబడింది మరియు సమానంగా ఉంటే, అంతర్గత ఉత్పత్తి కోడ్ ప్రకారం).

టాస్క్ 2.3

ప్రస్తుత ఆర్డర్‌లను పూర్తి చేయడానికి సరఫరాదారుల నుండి ఎన్ని వస్తువులను ఆర్డర్ చేయాలి.

డొమైన్ లాజిక్‌ని మళ్లీ విస్తరిద్దాము:

CLASS Supplier 'Поставщик';
companyName = DATA STRING[100] (Supplier);

supplier = DATA Supplier (Product);

unitsInStock 'Остаток на складе' = DATA NUMERIC[10,3] (Product);
reorderLevel 'Норма продажи' = DATA NUMERIC[10,3] (Product);

రిలేషనల్

select s.CompanyName, p.ProductName, sum(od.Quantity) + p.ReorderLevel — p.UnitsInStock as ToOrder
from Orders o
join [Order Details] od on o.OrderID = od.OrderID
join Products p on od.ProductID = p.ProductID
join Suppliers s on p.SupplierID = s.SupplierID
where o.ShippedDate is null
group by s.CompanyName, p.ProductName, p.UnitsInStock, p.ReorderLevel
having p.UnitsInStock < sum(od.Quantity) + p.ReorderLevel

ఫంక్షనల్

orderedNotShipped 'Заказано, но не отгружено' (Product p) = 
    GROUP SUM quantity(OrderDetail d) IF product(d) = p;
toOrder 'К заказу' (Product p) = orderedNotShipped(p) + reorderLevel(p) - unitsInStock(p);
SELECT companyName(supplier(Product p)), name(p), toOrder(p) WHERE toOrder(p) > 0;

నక్షత్రం గుర్తుతో సమస్య

మరియు చివరి ఉదాహరణ వ్యక్తిగతంగా నా నుండి. సోషల్ నెట్‌వర్క్ యొక్క లాజిక్ ఉంది. వ్యక్తులు ఒకరితో ఒకరు స్నేహంగా ఉండవచ్చు మరియు ఒకరినొకరు ఇష్టపడవచ్చు. ఫంక్షనల్ డేటాబేస్ కోణం నుండి ఇది ఇలా ఉంటుంది:

CLASS Person;
likes = DATA BOOLEAN (Person, Person);
friends = DATA BOOLEAN (Person, Person);

స్నేహం కోసం సాధ్యమైన అభ్యర్థులను కనుగొనడం అవసరం. మరింత అధికారికంగా, మీరు A, B, C వ్యక్తులందరినీ కనుక్కోవాలి అంటే A Bతో స్నేహం, మరియు B అనేది Cతో స్నేహం, A ఇష్టపడుతుంది C, కానీ A అనేది Cతో స్నేహితులు కాదు.
ఫంక్షనల్ డేటాబేస్ కోణం నుండి, ప్రశ్న ఇలా కనిపిస్తుంది:

SELECT Person a, Person b, Person c WHERE 
    likes(a, c) AND NOT friends(a, c) AND 
    friends(a, b) AND friends(b, c);

రీడర్ తన స్వంతంగా SQLలో ఈ సమస్యను పరిష్కరించడానికి ప్రోత్సహించబడతాడు. మీరు ఇష్టపడే వ్యక్తుల కంటే చాలా తక్కువ మంది స్నేహితులు ఉన్నారని భావించబడుతుంది. అందువల్ల అవి ప్రత్యేక పట్టికలలో ఉన్నాయి. విజయవంతమైతే, ఇద్దరు స్టార్లతో ఒక టాస్క్ కూడా ఉంది. అందులో స్నేహం సౌష్టవం కాదు. ఫంక్షనల్ డేటాబేస్లో ఇది ఇలా ఉంటుంది:

SELECT Person a, Person b, Person c WHERE 
    likes(a, c) AND NOT friends(a, c) AND 
    (friends(a, b) OR friends(b, a)) AND 
    (friends(b, c) OR friends(c, b));

UPD: మొదటి మరియు రెండవ నక్షత్రంతో సమస్యకు పరిష్కారం dss_కలికా:

SELECT 
   pl.PersonAID
  ,pf.PersonAID
  ,pff.PersonAID
FROM Persons                 AS p
--Лайки                      
JOIN PersonRelationShip      AS pl ON pl.PersonAID = p.PersonID
                                  AND pl.Relation  = 'Like'
--Друзья                     
JOIN PersonRelationShip      AS pf ON pf.PersonAID = p.PersonID 
                                  AND pf.Relation = 'Friend'
--Друзья Друзей              
JOIN PersonRelationShip      AS pff ON pff.PersonAID = pf.PersonBID
                                   AND pff.PersonBID = pl.PersonBID
                                   AND pff.Relation = 'Friend'
--Ещё не дружат         
LEFT JOIN PersonRelationShip AS pnf ON pnf.PersonAID = p.PersonID
                                   AND pnf.PersonBID = pff.PersonBID
                                   AND pnf.Relation = 'Friend'
WHERE pnf.PersonAID IS NULL 

;WITH PersonRelationShipCollapsed AS (
  SELECT pl.PersonAID
        ,pl.PersonBID
        ,pl.Relation 
  FROM #PersonRelationShip      AS pl 
  
  UNION 

  SELECT pl.PersonBID AS PersonAID
        ,pl.PersonAID AS PersonBID
        ,pl.Relation
  FROM #PersonRelationShip      AS pl 
)
SELECT 
   pl.PersonAID
  ,pf.PersonBID
  ,pff.PersonBID
FROM #Persons                      AS p
--Лайки                      
JOIN PersonRelationShipCollapsed  AS pl ON pl.PersonAID = p.PersonID
                                 AND pl.Relation  = 'Like'                                  
--Друзья                          
JOIN PersonRelationShipCollapsed  AS pf ON pf.PersonAID = p.PersonID 
                                 AND pf.Relation = 'Friend'
--Друзья Друзей                   
JOIN PersonRelationShipCollapsed  AS pff ON pff.PersonAID = pf.PersonBID
                                 AND pff.PersonBID = pl.PersonBID
                                 AND pff.Relation = 'Friend'
--Ещё не дружат                   
LEFT JOIN PersonRelationShipCollapsed AS pnf ON pnf.PersonAID = p.PersonID
                                   AND pnf.PersonBID = pff.PersonBID
                                   AND pnf.Relation = 'Friend'
WHERE pnf.[PersonAID] IS NULL 

తీర్మానం

ఇచ్చిన భావనను అమలు చేయడానికి ఇవ్వబడిన భాషా వాక్యనిర్మాణం కేవలం ఒక ఎంపిక మాత్రమే అని గమనించాలి. SQL ప్రాతిపదికగా తీసుకోబడింది మరియు దానితో సాధ్యమైనంత సారూప్యంగా ఉండాలనేది లక్ష్యం. అయితే, కొందరికి కీలకపదాల పేర్లు, వర్డ్ రిజిస్టర్లు మొదలైన వాటి పేర్లు నచ్చకపోవచ్చు. ఇక్కడ ప్రధాన విషయం భావన కూడా. కావాలనుకుంటే, మీరు C++ మరియు Python రెండింటినీ ఒకే విధమైన వాక్యనిర్మాణం చేయవచ్చు.

వివరించిన డేటాబేస్ భావన, నా అభిప్రాయం ప్రకారం, క్రింది ప్రయోజనాలను కలిగి ఉంది:

  • సులభం. ఇది సాపేక్షంగా ఆత్మాశ్రయ సూచిక, ఇది సాధారణ సందర్భాలలో స్పష్టంగా ఉండదు. కానీ మీరు మరింత క్లిష్టమైన కేసులను చూస్తే (ఉదాహరణకు, ఆస్టరిస్క్‌లతో సమస్యలు), అప్పుడు, నా అభిప్రాయం ప్రకారం, అటువంటి ప్రశ్నలను వ్రాయడం చాలా సులభం.
  • Инкапсуляция. కొన్ని ఉదాహరణలలో నేను ఇంటర్మీడియట్ ఫంక్షన్‌లను ప్రకటించాను (ఉదాహరణకు, అమ్మిన, కొనుగోలు మొదలైనవి), దీని నుండి తదుపరి విధులు నిర్మించబడ్డాయి. అవసరమైతే, వాటిపై ఆధారపడిన వాటి యొక్క లాజిక్‌ను మార్చకుండా, కొన్ని ఫంక్షన్‌ల లాజిక్‌ను మార్చడానికి ఇది మిమ్మల్ని అనుమతిస్తుంది. ఉదాహరణకు, మీరు అమ్మకాలు చేయవచ్చు అమ్మిన పూర్తిగా భిన్నమైన వస్తువుల నుండి లెక్కించబడ్డాయి, మిగిలిన తర్కం మారదు. అవును, దీన్ని CREATE VIEWని ఉపయోగించి RDBMSలో అమలు చేయవచ్చు. కానీ లాజిక్కులన్నీ ఇలా రాస్తే పెద్దగా చదవగలిగేలా కనిపించదు.
  • సెమాంటిక్ గ్యాప్ లేదు. అటువంటి డేటాబేస్ విధులు మరియు తరగతులపై (టేబుల్స్ మరియు ఫీల్డ్‌లకు బదులుగా) పనిచేస్తుంది. క్లాసికల్ ప్రోగ్రామింగ్‌లో లాగానే (ఒక పద్ధతి అనేది మొదటి పారామీటర్‌తో కూడిన ఫంక్షన్ అని మేము అనుకుంటే అది క్లాస్ రూపంలో ఉంటుంది). దీని ప్రకారం, సార్వత్రిక ప్రోగ్రామింగ్ భాషలతో "స్నేహితులను చేసుకోవడం" చాలా సులభం. అదనంగా, ఈ భావన చాలా క్లిష్టమైన కార్యాచరణను అమలు చేయడానికి అనుమతిస్తుంది. ఉదాహరణకు, మీరు ఇలాంటి ఆపరేటర్‌లను పొందుపరచవచ్చు:

    CONSTRAINT sold(Employee e, 1, 2019) > 100 IF name(e) = 'Петя' MESSAGE  'Что-то Петя продает слишком много одного товара в 2019 году';

  • వారసత్వం మరియు పాలిమార్ఫిజం. ఫంక్షనల్ డేటాబేస్‌లో, మీరు CLASS ClassP ద్వారా బహుళ వారసత్వాన్ని పరిచయం చేయవచ్చు: Class1, Class2 నిర్మాణాలు మరియు బహుళ పాలిమార్ఫిజమ్‌ను అమలు చేయడం. నేను బహుశా భవిష్యత్ కథనాలలో ఎలా సరిగ్గా వ్రాస్తాను.

ఇది కేవలం ఒక భావన అయినప్పటికీ, అన్ని ఫంక్షనల్ లాజిక్‌లను రిలేషనల్ లాజిక్‌గా అనువదించే జావాలో మేము ఇప్పటికే కొంత అమలును కలిగి ఉన్నాము. అదనంగా, ప్రాతినిధ్యాల తర్కం మరియు చాలా ఇతర విషయాలు దానికి అందంగా జతచేయబడ్డాయి, దీనికి ధన్యవాదాలు మనకు మొత్తం లభిస్తుంది వేదిక. ముఖ్యంగా, మేము RDBMS (ప్రస్తుతానికి PostgreSQL మాత్రమే)ని “వర్చువల్ మెషీన్”గా ఉపయోగిస్తాము. FDBMSకి తెలిసిన నిర్దిష్ట గణాంకాలు RDBMS క్వెరీ ఆప్టిమైజర్‌కు తెలియనందున ఈ అనువాదంతో కొన్నిసార్లు సమస్యలు తలెత్తుతాయి. సిద్ధాంతపరంగా, ఫంక్షనల్ లాజిక్ కోసం ప్రత్యేకంగా స్వీకరించబడిన నిర్దిష్ట నిర్మాణాన్ని నిల్వగా ఉపయోగించే డేటాబేస్ మేనేజ్‌మెంట్ సిస్టమ్‌ను అమలు చేయడం సాధ్యపడుతుంది.

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి