写在前面
InterSystems SQL
提供了一个特殊的 –>
运算符作为从相关表获取值的简写,而在某些常见情况下,无需指定显式 JOIN 的复杂性。此箭头语法可以代替显式连接语法使用,也可以与显式连接语法结合使用。箭头语法执行左外连接
。
箭头语法可用于引用类的属性或父表的关系属性。其他类型的关系和外键不支持箭头语法。不能在 ON 子句中使用箭头语法 (–>
)。
1. 属性引用
可以使用 –>
运算符作为从“引用的表”中获取值的简写。
例如,假设您定义了两个类:
Company:
Class Sample.Company Extends %Persistent [DdlAllowed]
{
/// The Company name
Property Name As %String;
}
员工:
Class Sample.Employee Extends %Persistent [DdlAllowed]
{
/// The Employee name
Property Name As %String;
/// The Company this Employee works for
Property Company As Company;
}
–>
运算符Employee
类包含一个属性,该属性是对 Company 对象的引用。在基于对象的应用程序中,可以使用点语法
遵循此参考。例如,要查找员工为其工作的公司的名称,请执行以下操作:
Set name = employee.Company.Name
您可以使用使用 OUTER JOIN
联接来联接 Employee
和 Company
表的 SQL
语句执行相同的任务:
SELECT Sample.Employee.Name, Sample.Company.Name AS CompName
FROM Sample.Employee LEFT OUTER JOIN Sample.Company
ON Sample.Employee.Company = Sample.Company.ID
使用 –>
运算符,可以更简洁地执行相同的 OUTER JOIN 操作:
SELECT Name, Company->Name AS CompName
FROM Sample.Employee
–>
运算符您可以随时使用 –>
运算符,只要您在表中有引用列;也就是说,其值是引用表的 ID 的列(实质上是外键的特殊情况)。在本例中,Sample.Employee 的“公司”字段包含 Sample.Company 表中的记录 ID。可以在查询中使用列表达式的任何位置使用 –> 运算符
。例如,在 WHERE 子句中:
SELECT Name,Company AS CompID,Company->Name AS CompName
FROM Sample.Employee
WHERE Company->Name %STARTSWITH 'G'
这等效于:
SELECT E.Name,E.Company AS CompID,C.Name AS CompName
FROM Sample.Employee AS E, Sample.Company AS C
WHERE E.Company = C.ID AND C.Name %STARTSWITH 'G'
–>
运算符可以在 GROUP BY 子句中使用 –> 运算符:
SELECT Name,Company->Name AS CompName
FROM Sample.Employee
GROUP BY Company->Name
–>
运算符您可以在 ORDER BY
子句中使用 –>
运算符:
SELECT Name,Company->Name AS CompName
FROM Sample.Employee
ORDER BY Company->Name
–>
运算符列的列别名或者引用 ORDER BY
子句中 –>
运算符列的列别名:
SELECT Name,Company->Name AS CompName
FROM Sample.Employee
ORDER BY CompName
支持复合箭头语法,如下面的示例所示。在此示例中,Cinema.Review 表包括 Film 字段,该字段包含 Cinema.Film 表的行 ID。Cinema.Film 表包括“类别”字段,该字段包含 Cinema.Category 表的行 ID。因此,Film->Category->CategoryName访问这三个表,以返回具有ReviewScore的每部电影的CategoryName:
SELECT ReviewScore,Film,Film->Title,Film->Category,Film->Category->CategoryName
FROM Cinema.Review
ORDER BY ReviewScore
2. 子表引用
可以使用 –>
运算符来引用子表。例如,如果 LineItems
是 Orders
表的子表,则可以指定:
SELECT LineItems->amount
FROM Orders
请注意,订单中没有名为 LineItems
的属性。LineItems
是包含金额字段的子表的名称。此查询在结果集中为每个 Order 行生成多行。它等效于:
SELECT L.amount
FROM Orders O LEFT JOIN LineItems L ON O.id=L.custorder
SELECT Patient->PA_ScreenNo,*
FROM DHCDoc_GCPBC_Base.Plan
3. 箭头语法权限
使用箭头语法时,您必须对两个表中引用的数据具有 SELECT
权限。您必须对引用的列具有表级 SELECT 特权或列级 SELECT 特权。使用列级权限时,您需要对被引用表的 ID 以及被引用的列具有 SELECT 权限。
以下示例演示了所需的列级特权:
SELECT Name,Company->Name AS CompanyName
FROM Sample.Employee
GROUP BY Company->Name
ORDER BY Company->Name
在上面的示例中,您必须具有列级 SELECT 特权才能 Sample.Employee.Name
、Sample.Company.Name
和 Sample.Company.ID
:
SET tStatement = ##class(%SQL.Statement).%New()
SET privchk1="%CHECKPRIV SELECT (Name,ID) ON Sample.Company"
SET privchk2="%CHECKPRIV SELECT (Name) ON Sample.Employee"
CompanyPrivTest
SET qStatus = tStatement.%Prepare(privchk1)
IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
SET rset = tStatement.%Execute()
IF rset.%SQLCODE=0 {WRITE !,"have Company privileges",! }
ELSE { WRITE !,"No privilege: SQLCODE=",rset.%SQLCODE,! }
EmployeePrivTest
SET qStatus = tStatement.%Prepare(privchk2)
IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
SET rset = tStatement.%Execute()
IF rset.%SQLCODE=0 {WRITE !,"have Employee privilege",! }
ELSE { WRITE !,"No privilege: SQLCODE=",rset.%SQLCODE }