MUMPS Globals:極端なデータベースプログラミング。 パート2

(Rob Tweed)
パート1を参照してください。

第2章SQL /リレーショナルデータベースとMUMPS



この章では、通常のSQLリレーショナルデータベースとMUMPSベースのデータベースの主な違いについて説明します。

グローバルとは何か、およびそれらを操作する方法をよりよく理解する必要がある場合は、 第1章をお読みください。

データ構造を定義する


基本から始めましょう-データを定義します。 例として、3つのテーブルで構成される単純なデータベースを使用します。

1.顧客テーブル(CUSTOMER)
2.注文表(ORDER)
3.個々の注文を構成するもののリストを含むテーブル(ITEM)



テーブル名は太字で示され、主キーには下線が引かれています。

カスタママー
custNo 一意の顧客番号
顧客名
アドレスクライアントアドレス
totalOrders 販売注文の総数

ご注文
注文番号なし
custNo 顧客番号(CUSTOMERテーブルの外部キー)
orderDate 注文日
invoiceDate請求書の日付
totalValue 注文値

アイテム
orderNo 注文番号(ORDERテーブルのキーに対応)。
itemNo アイテム番号
価格(すべての割引を考慮して)クライアントのアイテム価格。

1対多の関係を図に示します。 各顧客は多くの注文を行うことができ、各注文は多くのもので構成できます。

特定のクライアントの注文数(CUSTOMER.totalOrders)は、クライアントがORDERSテーブルに入れた注文の総数であり、その番号で識別されます。

注文価格(ORDER.totalValue)は、注文内のすべての物のコストの合計です。特定の各コストはITEM.priceフィールドによって決定されます。

フィールドCUSTOMER.totalOrdersおよびORDER.totalValueは、ユーザーが直接入力するものではありません-これらは計算フィールドです。

SQL /リレーショナルデータベースの場合、SQLを使用する前にこれらのテーブル定義をデータベースにロードする必要があり(CREATE TABLEを使用)、レコードを追加、変更、取得できます。

MUMPSはテーブル定義を使用する前に使用することを強制しないため、正式に事前に定義する必要なく、行をリポジトリに直接書き込むことができます。

それでも、SQLツールを介してデータにアクセスするには、MUMPSストレージにリレーショナルスキーマを透過的に重ね合わせることができることに注意することが重要です。 必要に応じて既存のMUMPSリポジトリにリレーショナルスキーマを追加し、正規化された形式でレコードにアクセスできます(構造が正規化に適している場合)。

これらの3つのテーブルは、次のグローバルを使用してMUMPSに表示されます。

CUSTOMERテーブル

^ CUSTOMER(custNo)=名前|アドレス| totalOrders

ORDERテーブル

^ ORDER(orderNo)= custNo | orderDate | invoiceDate | totalValue

ITEMテーブル

^ ITEM(orderNo、itemNo)=価格

CUSTOMERとORDERの関係は、グローバルを使用して表されます。

^ ORDERX1(custNo、orderNo)=””

彼は顧客番号ごとに注文番号を提供します。

MUMPSでは、任意のグローバル名を使用できます。 また、各テーブルに1つのグローバルを使用する(選択した)か、複数のテーブルまたはすべてのテーブルに同じグローバルを使用するかを選択できます。

たとえば、構造全体に1つのグローバルを使用できます。

^OrderDatabase(“customer”,custNo)= name_”~”_address_”~”_totalOrders ^OrderDatabase(“order”,orderNo)= custNo_”~”_orderDate_”~”_invoiceDate_”~”_totalValue ^OrderDatabase(“item”,orderNo,itemNo)=price ^OrderDatabase(“index1”,custNo,orderNo)=”” 

この記事の説明のために、テーブルごとにグローバルを使用することにしました。

また、ティルダ文字(〜)をグローバルのフィールド区切り文字として使用することも選択しました(他の文字を選択できます)。

データベースへのレコードの追加

非常に簡単な例から始めましょう。 CUSTOMERテーブルに新しいクライアントを追加します。

SQL

 INSERT INTO CUSTOMER (CustNo, Name, Address) VALUES (100, 'Chris Munt', 'Oxford') 

おたふく風邪

 Set ^CUSTOMER(100)= “Chris Munt”_"~"_"Oxford" 

「_」は、文字列を接着(連結)するための文字です。

右側に、チルダ記号で区切られた2つのフィールドを入力しました。 ちなみに、印刷できない文字を含め、任意の文字を区切り文字として使用できます。

私たちは書くことができます:

 Set ^CUSTOMER(100)= “Chris Munt”_$c(1)_"Oxford" 

関数$ c(1)は、「値が1のASCII文字」を意味します。
$ cは、$ char関数の短縮名です。

また、この場合、ASCII 1文字を使用してフィールドを区切ります。

もちろん、実際の状況では、INSERT要求(またはMUMPSコマンド)に代入されるデータは変数に保存されます。

SQL

 INSERT INTO CUSTOMER (custNo, name, address) VALUES (:custNo, :name, :address) 


ご注意 トランスレーター:ANSI SQLでは、変数を指定するために先行するコロンが使用されます。


おたふく風邪

 Set ^CUSTOMER(custNo)=name_"~"_address 

データベースからレコードを取得する

SQL

 SELECT A.name, A.address FROM CUSTOMER A WHERE A.custNo = :custNo 

おたふく風邪

 Set record=$get(^CUSTOMER(custNo)) Set name=$piece(record,"~",1) Set address=$piece(record,"~",2) 

$ get()関数の使用に関する注意。 これは、グローバルから値を抽出する便利な方法です。 要求されたアイテムが存在しない場合、$ get()はnull( "")を返します。

$ get()を使用していなかった場合、これを行う必要があります。

 Set record=^CUSTOMER(custNo) 

要求されたグローバル要素が存在しない場合、MUMPSは実行時エラーを返します(つまり、データが定義されていません)。

MUMPSのほとんどのコマンドおよび関数と同様に、$ get()の代わりに省略形の$ g()を使用できます。

 Set record=$g(^CUSTOMER(custNo)) 

データベースからレコードを削除する

SQL

 DELETE FROM CUSTOMER A WHERE A.custNo = :custNo 

おたふく風邪

 kill ^CUSTOMER(custNo) 

この単純な例には、データベースの論理的整合性を維持できるチェックがまだ含まれていないことに注意してください。 次に、これがどのように行われるかを示します。

複数のレコードを選択

SQL

 SELECT A.custNo, A.name, A.address FROM CUSTOMER A 

おたふく風邪

 s custNo=”” fs custNo=$order(^CUSTOMER(custNo)) Quit:custNo= “” do . Set record=$get(^CUSTOMER(custNo)) . Set name=$piece(record,"~",1) . Set address=$piece(record,"~",2) . Set totalOrders=$piece(record,"~",3) . ;        

ドット構文(ドット構文)を使用していることに注意してください。 ピリオドで始まる行は、doコマンドによって呼び出されるサブルーチンを表します(最初の行の終わりを参照)

コメントが示すように、サブプログラム内の各行で必要なすべてを実行できます(「;」で始まる最後の行)

MUMPSの$オーダー関数は、グローバルの力と柔軟性の柱の1つです。 通常、その作業の本質は、SQLおよびリレーショナルデータベースのみに精通している人には理解できないため、第1章で詳しく説明します。

$順序関数とグローバルを使用すると、キーが任意の値で始まり、任意の値で終わるテーブル内のすべての行をバイパスできます。 グローバルは階層的なリポジトリであることを理解することが重要です。 グローバルのインデックスを介してテーブルのキーをエミュレートしたため、作成された順序で行にアクセスすることはできません。$順序関数は、グローバルの各インデックス(キー)に個別に適用できます。

高レベルのデータアクセスのためのMUMPS関数の使用

実際には、コードの冗長性を再利用して排除するには、上記のMUMPSコマンドを関数に変換する必要があります。 そのような関数の例を以下に示します。

データベースに新しいレコードを追加する

 setCustomer(custNo,data) ;    If custNo="" Quit 0 Set ^CUSTOMER(custNo)=data("name")_"~"_data("address") Quit 1 

この関数は、次の方法で呼び出すことができます。

 kill data ;    data (    RAM) set data("name")="Rob Tweed" set data("address")="London" set custNo=101 set ok=$$setCustomer(custNo,.data) ; $$ ,    

データ関数のパラメーターの前のポイントに注意してください。 これはリンク呼び出しです。 データは単純な変数ではなくローカル配列なので、参照によって関数に渡します。

setCustomer関数は、別のプログラム(myFunctionsなど)に含まれている場合があります。 また、MUMPSのプログラムはグローバルに含まれているため、グローバルから関数を呼び出すには、$$ setCustomer ^ myFunctions(custNo、.data)を記述する必要があります

例:
 kill data ; clear down data local array set data("name")="Rob Tweed" set data("address")="London" set custNo=101 set ok=$$setCustomer^myFunctions(custNo,.data) 

$$ setCustomer()関数は、外部と呼ぶことができます。 OOPの用語では、これはパブリックに対応します。 別のプログラムに含まれていても、参照できます。 外部関数は、ある種のデータアクセス方法です。

クライアント番号としてnullを渡すと、$$ setCustomer()関数はゼロ(つまりfalse)を返します。 それ以外の場合、レコードは保存され、$$ setCustomer()は1(つまりtrue)を返します。 ok変数をチェックして、保存が完了したかどうかを確認できます。

CUSTOMERテーブルに計算フィールドtotalOrdersがあるため、コードでサポートします。

 setCustomer(custNo,data) ; if custNo="" Quit 0 ;    Set data(“totalOrders”)=0 Set orderNo=”” for set orderNo=$order(^ORDERX1(custNo,orderNo)) Quit:orderNo=”” do . set data(“totalOrders”)=data(“totalOrders”)+1 set ^CUSTOMER(custNo)=data("name")_"~"_data("address")_”~”_data(“totalOrders”) Quit 1 

計算フィールドについては、トリガーのセクションで引き続き説明します。

データベースからレコードを取得する

次の外部関数は、CUSTOMERテーブルから行を返します。

 getCustomer(custNo,data) ; new record kill data ; clear down data array if custNo="" Quit 0 set record=$get(^CUSTOMER(custNo)) set data("name")=$piece(record,"~",1) set data("address")=$piece(record,"~",2) set data("totalOrders")=$piece(record,"~",3) Quit 1 

この関数は次のように使用できます。

 S custNo=101 set ok=$$getCustomer(custNo,.data) 

指定されたクライアントの文字列から3つのフィールドを含むローカル配列を返します(または、参照によって渡されるため、変更します)。

データ(「名前」)
データ(「アドレス」)
データ(「totalOrders」)

データベースからレコードを削除する

次の外部関数は、CUSTOMERテーブルから行を削除します。

 deleteCustomer(custNo) ; if custNo="" Quit 0 kill ^CUSTOMER(custNo) Quit 1 

この関数は次のように使用できます。

 S custNo=101 S ok=$$deleteCustomer(custNo) 


ご注意 翻訳者: 3つのパートで、セカンダリインデックス、トリガー、およびトランザクションについて説明します。

第三部、エンディング。

Source: https://habr.com/ru/post/J176305/


All Articles