前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >SQL隐式联接(箭头语法)

SQL隐式联接(箭头语法)

作者头像
用户7741497
发布2022-06-06 13:54:48
发布2022-06-06 13:54:48
81400
代码可运行
举报
文章被收录于专栏:hml_知识记录hml_知识记录
运行总次数:0
代码可运行

SQL隐式联接(箭头语法)

InterSystems SQL提供了一个特殊的–>运算符,作为从相关表中获取值的快捷方式,而在某些常见情况下无需指定显式的JOIN即可。可以使用此箭头语法代替显式联接语法,也可以将其与显式联接语法结合使用。箭头语法执行左外部联接。

箭头语法可用于类的属性或父表的关系属性的引用。其他类型的关系和外键不支持箭头语法。不能在ON子句中使用箭头语法(–>)。

属性引用

可以使用- >操作符作为从“引用表”获取值的简写。 例如,假设定义了两个类:Company:

代码语言:javascript
代码运行次数:0
运行
复制
Class Sample.Company Extends %Persistent [DdlAllowed]
{
/// The Company name
Property Name As %String;
}

Employee:

代码语言:javascript
代码运行次数:0
运行
复制
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对象的引用。 在基于对象的应用程序中,可以使用点语法遵循此引用。 例如,要查找Employee工作的Company名称:

代码语言:javascript
代码运行次数:0
运行
复制
 Set name = employee.Company.Name

可以使用使用外部连接来连接EmployeeCompany表的SQL语句来执行相同的任务:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT Sample.Employee.Name, Sample.Company.Name AS CompName
FROM Sample.Employee LEFT OUTER JOIN Sample.Company
ON Sample.Employee.Company = Sample.Company.ID

使用- >操作符,可以更简洁地执行相同的外连接操作:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT Name, Company->Name AS CompName
FROM Sample.Employee

只要在表中有引用列,就可以使用–>运算符;也就是说,其列的值是被引用表的ID(本质上是外键的特殊情况)。在这种情况下,Sample.EmployeeCompany字段包含Sample.Company表中记录的ID。可以在可以在查询中使用列表达式的任何地方使用–>运算符。例如,在WHERE子句中:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT Name,Company AS CompID,Company->Name AS CompName
FROM Sample.Employee
WHERE Company->Name %STARTSWITH 'G'

使用–>运算符,可以更简洁地执行相同的OUTER JOIN操作:

这等效于:

代码语言:javascript
代码运行次数:0
运行
复制
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'

请注意,在这种情况下,此等效查询使用INNER JOIN

以下示例使用箭头语法访问Sample.Person中的“Spouse”字段。如示例所示,Sample.Employee中的Spouse字段包含Sample.Person中记录的ID。本示例返回Employee与其SpouseHome_State相同的Home_StateOffice_State的那些记录:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT Name,Spouse,Home_State,Office_State,Spouse->Home_State AS SpouseState
FROM Sample.Employee
WHERE Home_State=Spouse->Home_State OR Office_State=Spouse->Home_State

可以在GROUP BY子句中使用–>运算符:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT Name,Company->Name AS CompName
FROM Sample.Employee
GROUP BY Company->Name

可以在ORDER BY子句中使用–>运算符:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT Name,Company->Name AS CompName
FROM Sample.Employee
ORDER BY Company->Name

或在ORDER BY子句中为–>运算符列引用列别名:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT Name,Company->Name AS CompName
FROM Sample.Employee
ORDER BY CompName

支持复合箭头语法,如以下示例所示。在此示例中,Cinema.Review表包含“Film”字段,其中包含Cinema.Film表的行IDCinema.Film表包含Category字段,其中包含Cinema.Category表的行ID。因此,Film-> Category-> CategoryName访问以下三个表,以返回具有ReviewScore的每部电影的CategoryName

代码语言:javascript
代码运行次数:0
运行
复制
SELECT ReviewScore,Film,Film->Title,Film->Category,Film->Category->CategoryName
FROM Cinema.Review
ORDER BY ReviewScore

子表引用

可以使用–>运算符来引用子表。例如,如果LineItemsOrders表的子表,则可以指定:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT LineItems->amount
FROM Orders

请注意,在Orders中没有称为LineItems的属性。 LineItems是包含数量字段的子表的名称。该查询在结果集中为每个Order行生成多个行。它等效于:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT L.amount
FROM Orders O LEFT JOIN LineItems L ON O.id=L.custorder

其中ustustLineItems表的父引用字段。

箭头语法权限

使用箭头语法时,必须对两个表中的引用数据都具有SELECT权限。必须在被引用的列上具有表级SELECT权限或列级SELECT权限。使用列级权限,需要对被引用表以及被引用列的ID具有SELECT权限。

以下示例演示了所需的列级权限:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT Name,Company->Name AS CompanyName
FROM Sample.Employee
GROUP BY Company->Name
ORDER BY Company->Name

在上面的示例中,必须对Sample.Employee.NameSample.Company.NameSample.Company.ID具有列级SELECT权限:

代码语言:javascript
代码运行次数:0
运行
复制
// d ##class(PHA.TEST.SQL).arrow()
ClassMethod arrow()
{
    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 失败:" 
        DO $System.Status.DisplayError(qStatus) 
        QUIT
    }
    SET rset = tStatement.%Execute()
    IF rset.%SQLCODE=0 {
        WRITE !,"拥有Company权限",! 
    } ELSE {  
        WRITE !,"无权限: SQLCODE=",rset.%SQLCODE,! 
    }
EmployeePrivTest
    SET qStatus = tStatement.%Prepare(privchk2)
    IF qStatus'=1 {
        WRITE "%Prepare 失败:" 
        DO $System.Status.DisplayError(qStatus) 
        QUIT
    }
    SET rset = tStatement.%Execute()
    IF rset.%SQLCODE=0 {
        WRITE !,"拥有Employee权限",! 
    } ELSE {
        WRITE !,"无权限: SQLCODE=",rset.%SQLCODE 
    }
}
代码语言:javascript
代码运行次数:0
运行
复制
DHC-APP>d ##class(PHA.TEST.SQL).arrow()
 
拥有Company权限
 
拥有Employee权限

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SQL隐式联接(箭头语法)
  • 属性引用
  • 子表引用
  • 箭头语法权限
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档