This Question and Answer Set includes the following topics:
  • 一般的な質問

  • 一般的な質問
    Question:
    読み取り専用のクラスやテーブルを作成するには、どのようにすればいいでしょうか?
    Answer:
    ユーザがテーブルを編集する必要がない場合、抽象クラスとしてクラスをマークすることができます。 そうすれば、そのクラスは読み取り専用としてコンパイルされます。
    一部のユーザがテーブルを編集し、すべてのユーザがテーブルから読み取ることができるようにする場合は、以下を実行します。
    GRANT SELECT ON * TO PUBLIC.
    
    これは、新規のテーブルを作成するたびに実行する必要があります。
    一部のユーザが、すべてのテーブルに読み取りアクセスが必要な場合は、以下を実行します。
    GRANT SELECT ON * TO Select_Role
    
    次にアクセスが必要なユーザに対して、GRANT を使用して Select_Role を与えます。これは、新規のテーブルを作成するたびに実行する必要があります。
    常に新規のテーブルが作成されている場合、この GRANT コードをストアド・プロシージャなどに入れると、呼び出しが簡単になります。自動的にテーブルを作成しているユーザは、そのテーブルのすべての権限を持つことに注意してください。
    Question:
    現在、以下のように MS SQL Server から Caché にストアド・プロシージャを移植する作業を行っています (以下のコードは簡素化しています)。
    CREATE PROCEDURE UpdateName 
    
    @LastName varchar(35),
    @FirstName varchar(25),
    @NewKey int OUTPUT
    
    AS
    
    INSERT INTO NameTable (LastName, FirstName)
            VALUES @LastName, @FirstName
    
    SELECT @NewKey = @@Identity
    
    この例が SQL Server で自動増分列を使用しているのと同じ方法で、独自の ID 列を使用したいのですが、挿入後に ID 列の値を抽出する方法が分かりません。また、出力パラメータの設定方法も教えてください。
    Answer:
    DDL Create Procedure 文などを使用して、行うことができます。
    CREATE PROCEDURE UpdateName(
            INOUT pHandle %SQLProcContext, 
            LastName VARCHAR(35), 
            FirstName VARCHAR(25), 
            OUT NewKey INT) 
    LANGUAGE COS 
    { 
        Set NewKey=""
    
        &sql(INSERT INTO NameTable (LastName, FirstName)
                    VALUES :LastName, :FirstName)
    
        // %ROWID special variable contains the value of the ID column created
        If 'SQLCODE Set NewKey=%ROWID
    
        If $Get(pHandle)'=$$$NULLOREF 
            Set pHandle.SQLCode=SQLCODE,pHandle.RowCount=%ROWCOUNT 
    
        QUIT 
    }
    
    Question:
    顧客と注文の間に、親子リレーションシップを設定しています。 最新の注文と注文合計を見たいので、以下のクエリを使用しました。
        SELECT ID, Name,
            MAX(Order->Date),
            SUM(Order->TotalAmount)
        FROM Sales.Customer
    
    Date と TotalAmount は、(子の) Order テーブルの列です。これでほぼ正しく作動し適切な値が取得できますが、1 人の顧客が複数の注文をした場合でも、1 つの注文ごとに別の顧客とみなしてしまいます。顧客 1 人あたりの Max (最大値) や Sum (合計値) を得るには、どうすればよいでしょうか?
    Answer:
    あなたは実質的に親テーブルと子テーブルを結合し、SQL への Caché 拡張機能を使用して、結合に基づいたクエリ処理を行っているので、ご使用のクエリはあなたが要求した通りの結果を返しています (-> 構文を使用しないとしても、標準 SQL ではこのクエリは不正です)。あなたは顧客ごとの最新の注文と合計数を要求していますが、このクエリでは実際には正しい答えを返すことができません。このクエリが返す結果は、最新の注文とすべての顧客に対する合計であり、これが顧客の注文ごとに繰り返されます。あなたが得ようとするデータを求めるには、以下のようにいくつか方法があります。
        SELECT ID, Name,
            MAX(Order->Date),
            SUM(Order->TotalAmount)
        FROM Sales.Customer
        GROUP BY Customer.ID
    
    標準 SQL を使用すると、以下のようになります。
        SELECT P.ID, P.Name,
            (SELECT MAX(C.Date)
            FROM Sales.Order AS C
            WHERE C.CustomerID = P.ID),
            (SELECT SUM(C.TotalAmount)
            FROM Sales.Order AS C
            WHERE C.CustomerID = P.ID)
        FROM Sales.Customer AS P
    
    以下も使用できます (これも標準 SQL を使用しています)。
        SELECT ID, Name,
            MAX(Order.Date),
            SUM(Order.TotalAmount)
        FROM Sales.Customer, Sales.Order
        WHERE customer.id = Order.CustomerID
        GROUP BY Customer.ID