在prolog中实现数据库

时间:2017-02-27 17:05:25

标签: database prolog

我想实施某种"数据库"在Prolog。

我有两个想法来建模表和行:

% First one
client('B069','Laurent','769, rue de la LALALA','LLN','A1',10000).

% Second one
data(client,'B069',name,'Laurent').
data(client,'B069',adress,'69, rue de la LALALA').
data(client,'B069',town,'LLN').
data(client,'B069',cat,'A1').
data(client,'B069',amount,10000).

使用这两个模型,我可以分别制作一个" SELECT ID FROM client WHERE amount> 0"对于积极金额的客户:

% First one
client1_positive(Client) :- findall(ID,(data(client,ID,compte,Amount),Amount>0),Client).

% Second one
client2_positive(Client) :- findall(ID,(client(ID,_,_,_,_,Amount),Amount>0),Client).

它们都具有相同的输出;

?- client1_positive(Clients).
Client = ['B069'].

?- client2_positive(Clients).
Client = ['B069'].

但这是我的问题,因为我对Prolog很新,我完全不知道如何让它变得如此动态,例如" SELECT name FROM client WHERE ID =' B069&#39 ; &#34 ;.我可以为这个特定的SQL查询实现一个规则,但是我找不到实现更抽象规则的方法,因此可以解释每个查询。

对于如何在Prolog中建模这些数据,是否有最好的实践?关于如何在Prolog中提出更抽象的请求的一些想法(不是对我的问题的详细解答)?

非常感谢

2 个答案:

答案 0 :(得分:2)

考虑如何使用关系数据库执行此操作。您可能有一个Client表,其中包含客户端ID(密钥),客户端名称,地址,电话和其他联系信息的记录。你不会想要一个单独的姓名,地址,电话等记录。这太麻烦了。

对于与客户端有一定关系的客户端数据,您将拥有单独的表(一对一,多对一,多对多,......)。如果客户端可能有多组联系人信息,那么这是联系人信息和客户端之间的多对一关系,因此您需要设置一个单独的ContactInfo表,其中“contact_info_id”作为主键,并且会有内容contact_info_id,客户ID,联系信息的记录。对于您的示例中的金额,您将拥有一个Amount表,其记录包含金额ID(密钥),客户ID,金额。

要在Prolog中执行此操作,您的结构基本相同。设置client数据和amount数据:

% clients
client('B069', 'John Doe', '123 Main St', 123-456-1234).
client('B070', 'Jane Smith', '100 West Elm', 999-999-8888).
...

% amounts
amount('A010', 'B069', 10000).
amount('A010', 'B070', 10100).
...

以上可以是一对一或多对一。

相当于查询:SELECT name FROM client WHERE ID = 'B069'将是:

?- client('B069', Name, Address, Phone).

您选择的正数将是:

client_positive(Clients) :-
    findall(ClientId, (amount(_, ClientId, Amount), Amount > 0), Clients).

答案 1 :(得分:0)

你的第一种方法很好。例如,你可能需要第二个,例如a 一个人可以拥有多个地址。

查询只是一个带变量的术语:

Option Explicit

Sub Main()
    Dim cell As Range, newRowRng As Range, myRow As Range, f As Range
    Dim firstAddress As String

    With Sheets("myDataSheetName") '<--| change "myDataSheetName" to your actual sheet name
        With .Range("A1", .cells(.Rows.Count, "S").End(xlUp)) '<--| reference its columns A:S range from row 1 (header) down to the one corresponding to last column S not empty row
            FormatDefault .cells '<--| set all range cells to their "default" format
            .AutoFilter Field:=19, Criteria1:="New row" '<--| filter column S cells with "New row"
            If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 1 Then Set newRowRng = .Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible) '<--| if any filtered cells other than headers then set 'newRowRng' to them
            .Parent.AutoFilterMode = False '<--| remove autofilter
        End With

        If newRowRng Is Nothing Then Exit Sub '<--| if no "newRow" in column S then exit sub

        For Each myRow In Intersect(newRowRng, .Columns(1)) '<--| loop through column A "filtered" cells
            If myRow.Value = myRow.Offset(-1).Value Then '<--| if current cell value equals the one above
                With Intersect(newRowRng, myRow.EntireRow) '<--| reference current cell entire data row
                    Set f = .Find(what:="y", LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False) '<--| search it for "y"
                    If Not f Is Nothing Then '<--| if found
                        firstAddress = f.Address '<--| store first found cell address
                        Do '<--| start a loop
                            If Len(f.Offset(-1)) = 0 Then FormatCell f '<--| if empty cell above current found cell thne set this latter format
                            Set f = .FindNext(f) '<--| search for the next "y"
                        Loop While Not f.Address = firstAddress '<--| exit whne 'Find()' wraps back to first found cell
                    End If
                End With
            End If
        Next
    End With

End Sub

Sub FormatDefault(rng As Range)
    With rng
        With .Font
            .Color = 0
            .TintAndShade = 0
        End With
        With .Interior
            .Color = 16777215
            .PatternColorIndex = -4142
            .TintAndShade = 0
        End With
    End With
End Sub

Sub FormatCell(rng As Range)
    With rng
        With .Font
            .Color = -16383844
            .TintAndShade = 0
        End With
        With .Interior
            .PatternColorIndex = xlAutomatic
            .Color = 13551615
            .TintAndShade = 0
        End With
    End With
End Sub

您可以使用任何参数作为查询中的键。您的Prolog可能不会对所有这些内容编制索引,这可能是也可能不是问题。

| ?- client('B069',Name,Adress,Town,Cat,Amount).
Cat = 'A1',
Name = 'Laurent',
Town = 'LLN',
Adress = '769, rue de la LALALA',
Amount = 10000 ?

如果有多个答案,则会通过回溯返回。 Findall将它们收集在一个列表中,这可能是您想要的,也可能不是。

如果通过&#34;动态&#34;您的意思是在数据库中添加和删除内容,然后您可以| ?- client(Key,'Laurent',_,_,_,_). Key = 'B069' ? assert/1