
【Salesforce】SQLとSOQLはここが違う(その2)
はじめに
こんにちは。CREFILでエンジニアをしている松井です。
この記事では、前回の記事に引き続き、SQLとSOQLの違いについてご紹介ししていきます。
項番が5からはじまっていますが、1 ~ 4は前回の記事にあります。
前回の記事が未読でも問題なく理解できる内容ではありますが、よろしければ是非、前回分もご覧ください。
SQLとSOQLの違い
ここからは、前回の記事と同様に、具体例を挙げながら、SQLとSzQOLでそれぞれどのような記述になるか、ご説明していきます。
例では、次のようなデータ構造のテーブル(オブジェクト)群を想定します。

5. SELECT *が指定できない
(ケース5.1)取引先の全項目を取得したい
SQLでは、SELECT句に"*"(アスタリスク)を指定することで、すべての項目を取得することができます。
SQL
SELECT *
FROM Account
SOQLでは、"*"の代わりに"FIELDS()"という関数で実現できます。
SOQL
SELECT FIELDS(ALL)
FROM Account
ORDER BY Id
LIMIT 200
"FIELDS"の引数には、次の3種類があります。
FIELDS(ALL) ・・・オブジェクトのすべての項目
FIELDS(STANDARD) ・・・オブジェクトのすべての標準項目
FIELDS(CUSTOM)・・・オブジェクトのすべてのカスタム項目
"FIELDS"を使用する場合は、制約として、検索結果の件数を200件以下に抑える必要があります。
そのために、LIMIT句で"LIMIT 200"と指定しています。
"ORDER BY"によるソート順の指定は、IDの昇順で先頭200件となるようにつけただけなので、ランダムな200件でよい場合には不要です。
ちなみに、SOQLにはLIMIT句とあわせて使えるOFFSET句もあります。
このあたりは標準SQLではなく、データベース製品によって方言があるところですが、PostgreSQLと同じ文法でシンプルに記述ができます。
200件目以降の続きで201件目から400件目まで取得するのであれば、OFFSET句を指定して次のように記述できます。
SOQL
SELECT FIELDS(ALL)
FROM Account
ORDER BY Id
LIMIT 200
OFFSET 201
6. SELECT DISTINCTが指定できない
(ケース6.1)取引先責任者の部署と取引先の社名の一意のリストを抽出したい
SQLなら、DISTINCTキーワードを指定することで重複データが削除され、一意のデータを抽出することができます。
SQL
SELECT DISTINCT acct.Name, ctac.Department
FROM Account acct
JOIN Contact ctac
ON acct.Id = ctac.AccountId
SOQLでは、DISTINCTが指定できないので、"GROUP BY"で対象の項目をすべてグループ化して対応します。
SOQL
SELECT Account.Name, Department
FROM Contact
GROUP BY Account.Name, Department
SQLでも同様の書き方は可能ですが、項目数が多いときは面倒なので、ついDISTINCTを使いがちです。
一応、DISTINCTはありませんが、SOQLにも"COUNT_DISTINCT()"という集計関数があるので、一意の値の個数をカウントするという場合には、その関数で対応できます。
7. SOQLではNULLも値
(ケース7.1)請求先郵便番号の値が未設定で、かつ、送付先郵便番号に値が設定されている取引先を抽出したい
SQL、というかリレーショナルデータベースモデルにおいては、"NULL"は値ではなく、値が存在しない状態を表現するキーワードです。
そのため、NULLを条件に指定する場合は専用の"IS NULL"演算子で記述します。否定であれば"IS NOT NULL"です。
SQL
SELECT Id, Name
FROM Account
WHERE BillingPostalCode IS NULL
AND ShippingPostalCode IS NOT NULL
SOQLでは、NULLも通常の値と同様の記述となります。
SOQL
SELECT Id, Name
FROM Account
WHERE BillingPostalCode = null
AND ShippingPostalCode != null
(ケース7.2)請求先郵便番号の値が未設定、または、'103-0006'である取引先を検索したい
SQLでは、"OR"でつないで記述することになります。
SQL
SELECT Id, Name
FROM Account
WHERE BillingPostalCode IS NULL
OR BillingPostalCode = '103-0006'
SOQLではIN句の要素として、リテラル値とならべてNULLを記述することができます。
(正確に言えば、SQLでも記述はできますが、3値論理なので期待通りの動作はしません。)
SOQL
SELECT Id, Name
FROM Account
WHERE BillingPostalCode IN (null, '103-0006')
もちろん、SQLと同様に"OR"でつなげる記述も可能です。
8. SOQLにはNOT LIKE演算子がない
(ケース8.1)名称の先頭が"株式会社"ではない取引先を抽出したい
SQLでは"NOT LIKE"で対応できます。
SQL
SELECT Id, Name
FROM Account
WHERE Name NOT LIKE '株式会社%'
SOQLでも"LIKE"演算子が存在し、ワイルドカードで"%"と"_"がサポートされています。
% ・・・0 個以上の文字に一致します
_ ・・・1 文字のみに一致します
しかし、"NOT LIKE"演算子はないため、否定の場合はSQLと同じ記述ではエラーとなります。
ただ、"NOT"という論理演算子はあるので、"LIKE"を使用した式に対して否定をかけることで対応できます。
SOQL
SELECT Id, Name
FROM Account
WHERE NOT (Name LIKE '株式会社%)'
NOT内を"()"で囲んでいますが、わかりやすくつけたものなので、なくても問題ありません。
SQLでも同様の記述は可能です。
本当にささいな違いですが、" = "と" != "、"IN"と"NOT IN"のように他は対となる演算子があるのに、"LIKE"に対する"NOT LIKE"だけ存在しないのは不思議です。
9. SOQLにはコメントがない
SQLでは行コメント、ブロックコメントがあります。
SQL
-- 行コメント
/*
ブロックコメント
*/
SELECT Id, Name
FROM Account
SOQLは、SQLの行コメントとブロックコメントのどちらもサポートされていません。
クエリを試行錯誤しながら作成しているときには、ちょっと部分的にコメントアウトして試しに実行したい場面もあると思いますが、残念ながらSOQLではできません。
おわりに
いかがでしたでしょうか。
一部のみではありますが、SQLとSOQLの違いで注意が必要なことのご紹介でした。
ご覧いただき本当にありがとうございました。