2017-02-27 60 views
0

我想在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從客戶WHERE量> 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的我完全不知道我怎麼可以使動態,如「選擇的名字從客戶WHERE ID =‘B069’」。我可以爲這個特定的SQL查詢實現一個規則,但是我找不到實現更抽象的規則的方法,因此每個查詢都可以被解釋。

如何在Prolog中對這些數據建模是否有最佳實踐?還有一些想法(不是我的問題的詳細答案)如何在Prolog中使請求更加抽象?

非常感謝

回答

2

想想如何在關係型數據庫中做到這一點。您可能會有一個客戶表,其中包含客戶端ID(密鑰),客戶名稱,地址,電話和其他聯繫信息。你不會想要一個單獨的記錄名稱,地址,電話等。這太麻煩了。

對於與客戶端有一定關係的客戶端數據(一對一,多對一,多對多......),您應該有單獨的表。如果一個客戶可能有多個聯繫信息,那麼這就是聯繫信息和客戶之間的多對一關係,所以你需要設置一個單獨的ContactInfo表,其中包含一個「contact_info_id」作爲主鍵,將具有內容contact_info_id,客戶端ID,聯繫信息的記錄。在你的例子中的金額的情況下,你將有一個金額表,其中包含金額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). 
+0

謝謝,幫助我。你是否知道這個模型,我可以如何獲得客戶端的第二個參數,例如'nnth_arg(+ Predicate,+ Nth,-Argument)'的規則。這種規則是否存在? – tomatediabolik

+0

@tomatediabolik在這種情況下,你知道每個參數位置的含義。按索引選擇參數的用例是什麼?通常,你可能有'client_phone(ClientId,Phone): - client(CllientId,_,_,Phone).'或類似的東西。如果你真的需要通過索引來挑選它,你可以使用'arg/3'('arg(+ Nth,+ Term,-Argument)')來獲得一個詞的第n個參數。沒有關於你的用例的更多信息,我不知道還有什麼要說的。 – lurker

0

你的第一個辦法是罰款。例如,如果某個人可以擁有多個地址,則可能需要第二個地址。

查詢是隻是變量的一個術語:

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

你可以使用任何參數,查詢中的關鍵。您的Prolog可能不會對所有這些索引進行索引,這可能是也可能不是問題。

| ?- client(Key,'Laurent',_,_,_,_). 
Key = 'B069' ? 

如果有多個答案,那麼他們通過回溯返回。 Findall將它們收集在一個列表中,這可能是也可能不是你想要的。

如果按照「動態」您的意思是從數據庫中添加和刪除內容,則可以使用assert/1retract/1