【转】四、可空类型Nullable到底是什么样鬼

Core data services(以下简称CDS)能够指两样东西,一个是HANA
CDS,一个是ABAP CDS

【转】四、可空类型Nullable<T>到底是何等鬼

如我辈所知,HANA CDS只协助HANA数据库,ABAP
CDS理论上辅助多种数据库供应商,结果是,ABAP
CDS相比较之下要少一些效益。由此,在好几意况下,无法采用ABAP
CDS解决问题时,可以接纳一种变更的方法,即通过ABAP Managed Database
Procedures
(AMDP)创建ABAP CDS Table Function

值类型为何不可以为空

先是我们都通晓引用类型默认值都是null,而值类型的默认值都有非null。

图片 1

何以引用类型可以为空?因为引用类型变量都是保留一个目的的地点引用(就像一个url对应一个页面),而引用类型值为null的时候是变量值指向了一个空引用(如同一个空的url)

图片 2

这为啥值不可能有空值呢?其实很粗略,因为如int值范围是-2147483648到2147483647。其中根本就没有给null值留那么一个职位。

图片 3

 

俺们怎么需要用到可空类型

举个栗子吧,大家定义一个人(Person),它有多少个特性出生日期(Begin提姆(Tim)e)、死亡日期(End提姆e)、年龄(Age)。

一旦这个人还健在凡间,请问怎么给死亡日期赋值?有人很聪明伶俐说“为空啊”。是的,这就是我们的需要。

微软在C#2.0的时候就为我们引入了可null值类型( System.Nullable<T> ),那么下边来定义Person类。

 1 public class Person
 2 {
 3     /// <summary>
 4     /// 出生日期
 5     /// </summary>
 6     public DateTime BeginTime { get; set; }
 7     /// <summary>
 8     /// 死亡日期
 9     /// </summary>
10     public System.Nullable<DateTime> EndTiem { get; set; }
11     public int Age
12     {
13         get
14         {
15             if (EndTiem.HasValue)//如果挂了(如果有值,证明死了)
16             {
17                 return (EndTiem.Value - BeginTime).Days;
18             }
19             else//还没挂
20             {
21                 return (DateTime.Now - BeginTime).Days;
22             }
23         }
24     }
25 }

 

这样,大家就可以很容易获取一个人的年华了。

static void Main(string[] args)
{
    Person p1 = new Person()
    {
        BeginTime = DateTime.Parse("1990-07-19")
    };

    Person p2 = new Person()
    {
        BeginTime = DateTime.Parse("1893-12-26"),
        EndTiem = DateTime.Parse("1976-09-09")
    };

    Console.WriteLine("我今年" + p1.Age + "岁。");
    Console.WriteLine("毛爷爷活了" + p2.Age + "岁。");

    Console.ReadKey();
}

本文链接:http://www.cnblogs.com/hhelibeb/p/8057788.html

可空类型的兑现

我们前边用到了 System.Nullable<Date提姆e> 来代表可空时间档次,其实平日大家用得更多的是 Date提姆e? 直接在类型T前面加一个问号,这二种是一样的。多亏了微软的语法糖。

大家来看望 System.Nullable<T> 到底是何物。

图片 4

搜噶,原来是一个构造。还察看了咱们属性的
HasValue和Value属性。原来竟这么简单。一个布局五个属性,一个存值,一个存是否有值。那么下边我们也来尝试吧。

图片 5

害羞,让我们失望了。前边我们就说过了,值类型是不可以赋值null的(结构也是值类型)。

咋做!肿么办!不对啊,微软团结也是概念的构造,它怎么能够直接赋值null呢。(奇怪,奇怪,毕竟是人家微软温馨搞得,可能得到了出格的对待吗)

只是,这样就让大家止步了吧?NO!我们都知情,看微软的IL(中间语言)的时候,就像脱了它的行装一样,很多时候不晓得的地点都足以看个究竟,下边我们就去脱衣裳。

第一,我们用二种不同的不二法门给可空类型赋值。

static void Main(string[] args)
{

    System.Nullable<int> number1 = null;

    System.Nullable<int> number2 = new System.Nullable<int>();

    System.Nullable<int> number3 = 23;

    System.Nullable<int> number4 = new System.Nullable<int>(88);

    Console.ReadKey();
}    

 

接下来用reflector看编译后的IL。

图片 6

原来如此,可空类型的赋值直接等效于构造实例。赋null时其实就是调用空构造函数,有值时就就把值传入带参数的构造函数。(豁然开朗又一村。如此,我们是否足以跟着下边截图中的 MyNullable<T> 继续模拟可空类型呢?且继续往下看。)

public struct MyNullable<T> where T : struct
{
    //错误    1    结构不能包含显式的无参数构造函数 
    //还好 bool默认值就是false,所以这里不显示为 this._hasValue = false也不会有影响
    //public MyNullable()
    //{
    //    this._hasValue = false;
    //}
    public MyNullable(T value)//有参构造函数
    {
        this._hasValue = true;
        this._value = value;
    }

    private bool _hasValue;

    public bool HasValue//是否不为空
    {
        get { return _hasValue; }
    }

    private T _value;
    public T Value//值
    {
        get
        {
            if (!this._hasValue)//如没有值,还访问就抛出异常
            {
                throw new Exception(" 可为空的对象必须具有一个值");
            }
            return _value;
        }
    }
}

 

哟西,基本上已经模拟出了可空类型出来的。(不过大家依旧无法平素赋值,只可以通过构造函数的办法来行使自定义的可空类型)。

所有代码如下:

图片 7图片 8

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 可空类型
{
    public class Person
    {
        /// <summary>
        /// 出生日期
        /// </summary>
        public DateTime BeginTime { get; set; }
        /// <summary>
        /// 死亡日期
        /// </summary>
        public MyNullable<DateTime> EndTiem { get; set; } //这里改用MyNullable
        /// <summary>
        /// 年龄
        /// </summary>
        public double Age
        {
            get
            {
                if (EndTiem.HasValue)//如果挂了(如果有值,证明死了)
                {
                    return (EndTiem.Value - BeginTime).Days / 365;
                }
                else//还没挂
                {
                    return (DateTime.Now - BeginTime).Days / 365;
                }
            }
        }
    }

    public struct MyNullable<T> where T : struct
    {
        //错误    1    结构不能包含显式的无参数构造函数 
        //还好 bool默认值就是false,所以这里不显示为 this._hasValue = false也不会有影响
        //public MyNullable()
        //{
        //    this._hasValue = false;
        //}
        public MyNullable(T value)//有参构造函数
        {
            this._hasValue = true;
            this._value = value;
        }

        private bool _hasValue;

        public bool HasValue//是否不为空
        {
            get { return _hasValue; }
        }

        private T _value;
        public T Value//值
        {
            get
            {
                if (!this._hasValue)//如没有值,还访问就抛出异常
                {
                    throw new Exception(" 可为空的对象必须具有一个值");
                }
                return _value;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person()
            {
                BeginTime = DateTime.Parse("1990-07-19")
            };

            Person p2 = new Person()
            {
                BeginTime = DateTime.Parse("1893-12-26"),
                EndTiem = new MyNullable<DateTime>(DateTime.Parse("1976-09-09"))//这里使用MyNullable的有参构造函数
            };

            Console.WriteLine("我今年" + p1.Age + "岁。");
            Console.WriteLine("毛爷爷活了" + p2.Age + "岁。");

            Console.ReadKey();
        }

    }
}

View Code

 

和类其它可空类型得出了同一的结果。

图片 9

注:本文的基本点理论内容已经包含在前边的英特尔P介绍著作:ABAP中的AMDP(ABAP-Managed
Database Procedures )

中,相相比它,本文更像一个step by step教程。

总结

  • 可空类型是构造(也就是值类型)
  • 从而可空类型的null值和引用类型的null是不同等的。(可空类型的并不是引用类型的null,而是用结构的另一种象征方法来表示null)

图片 10

 

有同学问,咋样才方可做到直接赋值呢?这个自己也从未怎么好的办法,或许需要编译器的支撑。

以上内容都是瞎扯。希望能对你有那么一点点用处,感谢阅读。

(首发链接:http://www.cnblogs.com/zhaopei/p/5537759.html )

 

 


 

============== 2016-06-05更新==============

地方我们指出了疑义“何以才得以成功直接赋值呢”,本来我是没有好的解决办法。这里要谢谢我们的园友@冲杀给我提供了好的解决方案。

implicit(关键字用于讲明隐式的用户定义类型转换运算符。)

public static implicit operator MyNullable<T>(T value)
{
       return new MyNullable<T>(value);
}

只需要在 struct
MyNullable<T> 中添加上述代码,就足以从来赋值了。(功用等效于是直接重写了“=”赋值符号)

图片 11

图片 12

总体代码如下:

图片 13图片 14

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace test
{
    public class Person
    {
        /// <summary>
        /// 出生日期
        /// </summary>
        public DateTime BeginTime { get; set; }
        /// <summary>
        /// 死亡日期
        /// </summary>
        public MyNullable<DateTime> EndTiem { get; set; } //这里改用MyNullable
        /// <summary>
        /// 年龄
        /// </summary>
        public double Age
        {
            get
            {
                if (EndTiem.HasValue)//如果挂了(如果有值,证明死了)
                {
                    return (EndTiem.Value - BeginTime).Days / 365;
                }
                else//还没挂
                {
                    return (DateTime.Now - BeginTime).Days / 365;
                }
            }
        }
    }

    public struct MyNullable<T> where T : struct
    {
        //错误    1    结构不能包含显式的无参数构造函数 
        //还好 bool默认值就是false,所以这里不显示为 this._hasValue = false也不会有影响
        //public MyNullable()
        //{
        //    this._hasValue = false;
        //} 

        public MyNullable(T value)//有参构造函数
        {
            this._hasValue = true;
            this._value = value;
        }

        private bool _hasValue;

        public bool HasValue//是否不为空
        {
            get { return _hasValue; }
        }

        private T _value;
        public T Value//值
        {
            get
            {
                if (!this._hasValue)//如没有值,还访问就抛出异常
                {
                    throw new InvalidOperationException(" 可为空的对象必须具有一个值");
                }
                return _value;
            }
        }

        public static implicit operator MyNullable<T>(T value)
        {
            return new MyNullable<T>(value);
        } 
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person()
            {
                BeginTime = DateTime.Parse("1990-07-19")
            };

            Person p2 = new Person()
            {
                BeginTime = DateTime.Parse("1893-12-26"),
                EndTiem = DateTime.Parse("1976-09-09") 
                //new MyNullable<DateTime>(DateTime.Parse("1976-09-09"))
                //这里使用MyNullable的有参构造函数
            };

            Console.WriteLine("我今年" + p1.Age + "岁。");
            Console.WriteLine("毛爷爷活了" + p2.Age + "岁。"); 

            Console.ReadKey();
        }

    }
}

View Code

 

如此,大家早已成功了自定义可空类型的直白赋值。但只是局部,假使想要赋值null呢?

图片 15

相同依旧出现了最先导的编译错误。大家想到既然上边的值赋值可以重新(隐式转换),这null应该也得以啊(null是援引类型的一个特定值)。

再加一个重载:

//隐式转换
public static implicit operator MyNullable<T>(string value)
{
    if (value == null)
        return new MyNullable<T>();
    throw new Exception("赋值右边不能为字符串");
    //这里不知道是否可以在编译期间抛出错误(或者怎样限制只能传null)
}

 

如此可以满足我们的急需了(并无丰富)。

图片 16

可惜美中不足,假设给 p2.EndTiem 赋值一个非空字符串时,要运行时才会报错(而系统的可空类型会在编译期就报错)。不亮堂大神们可有解!!

即使这样,能完成直接赋值如故让自家小小激动了一把。为此,特意查了下紧要字 implicit operator ,又是让我不大激动了一把,大家不但可以“重写”赋值,我们仍可以够“重写”+

  • * / % & | ^ << >> == != > < >= <=等运算符。

下边我们先来“重写”下自定义可空类型的可比(==)运算符。

//"重写"比较运算符
public static bool operator ==(MyNullable<T> operand, MyNullable<T> operand2)
{
    if (!operand.HasValue && !operand2.HasValue)
    {
        return true;
    }
    else if (operand.HasValue && operand2.HasValue)
    {
        if (operand2.Value.Equals(operand.Value))
        {
            return true;
        }
    }
    return false;
}

//"重写"比较运算符
public static bool operator !=(MyNullable<T> operand, MyNullable<T> operand2)
{
    return !(operand == operand2);
}

 

Console.WriteLine("p1.EndTiem == null," + (p1.EndTiem == null).ToString());
Console.WriteLine("p2.EndTiem == null," + (p2.EndTiem == null).ToString());
Console.WriteLine("p1.EndTiem == DateTime.Parse(1976-09-09)," + (p1.EndTiem == DateTime.Parse("1976-09-09")).ToString());
Console.WriteLine("p2.EndTiem == DateTime.Parse(1976-09-09)," + (p2.EndTiem == DateTime.Parse("1976-09-09")).ToString());

p1.EndTiem = DateTime.Parse("2016-06-06");
p2.EndTiem = null;
Console.WriteLine();
Console.WriteLine("赋值 p1.EndTiem = DateTime.Parse(2016-06-06)  p2.EndTiem = null 后:");
Console.WriteLine("p1.EndTiem == null," + (p1.EndTiem == null).ToString());
Console.WriteLine("p2.EndTiem == null," + (p2.EndTiem == null).ToString());
Console.WriteLine("p1.EndTiem == DateTime.Parse(2016-06-06)," + (p1.EndTiem == DateTime.Parse("2016-06-06")).ToString());
Console.WriteLine("p2.EndTiem == DateTime.Parse(2016-06-06)," + (p2.EndTiem == DateTime.Parse("2016-06-06")).ToString());

图片 17

结果完全符合!

全体代码如下:

图片 18图片 19

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace test
{
    public class Person
    {
        /// <summary>
        /// 出生日期
        /// </summary>
        public DateTime BeginTime { get; set; }
        /// <summary>
        /// 死亡日期
        /// </summary>
        public MyNullable<DateTime> EndTiem { get; set; } //这里改用MyNullable
        /// <summary>
        /// 年龄
        /// </summary>
        public double Age
        {
            get
            {
                if (EndTiem.HasValue)//如果挂了(如果有值,证明死了)
                {
                    return (EndTiem.Value - BeginTime).Days / 365;
                }
                else//还没挂
                {
                    return (DateTime.Now - BeginTime).Days / 365;
                }
            }
        }
    }

    public struct MyNullable<T> where T : struct
    {
        //错误    1    结构不能包含显式的无参数构造函数 
        //还好 bool默认值就是false,所以这里不显示为 this._hasValue = false也不会有影响
        //public MyNullable()
        //{
        //    this._hasValue = false;
        //} 

        public MyNullable(T value)//有参构造函数
        {
            this._hasValue = true;
            this._value = value;
        }

        private bool _hasValue;

        public bool HasValue//是否不为空
        {
            get { return _hasValue; }
        }

        private T _value;
        public T Value//值
        {
            get
            {
                if (!this._hasValue)//如没有值,还访问就抛出异常
                {
                    throw new InvalidOperationException(" 可为空的对象必须具有一个值");
                }
                return _value;
            }
        }

        //隐式转换
        public static implicit operator MyNullable<T>(T value)
        {
            return new MyNullable<T>(value);
        }

        //隐式转换
        public static implicit operator MyNullable<T>(string value)
        {
            if (value == null)
                return new MyNullable<T>();
            throw new Exception("赋值右边不能为字符串");
            //这里不知道是否可以在编译期间抛出错误(或者怎样限制只能传null)
        }

        //"重写"比较运算符
        public static bool operator ==(MyNullable<T> operand, MyNullable<T> operand2)
        {
            if (!operand.HasValue && !operand2.HasValue)
            {
                return true;
            }
            else if (operand.HasValue && operand2.HasValue)
            {
                if (operand2.Value.Equals(operand.Value))
                {
                    return true;
                }
            }
            return false;
        }

        //"重写"比较运算符
        public static bool operator !=(MyNullable<T> operand, MyNullable<T> operand2)
        {
            return !(operand == operand2);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person()
            {
                BeginTime = DateTime.Parse("1990-07-19")
            };

            Person p2 = new Person()
            {
                BeginTime = DateTime.Parse("1893-12-26"),
                EndTiem = DateTime.Parse("1976-09-09")
                //new MyNullable<DateTime>(DateTime.Parse("1976-09-09"))
                //这里使用MyNullable的有参构造函数
            };

            Console.WriteLine("我今年" + p1.Age + "岁。");
            Console.WriteLine("毛爷爷活了" + p2.Age + "岁。");
            Console.WriteLine();

            Console.WriteLine("p1.EndTiem == null," + (p1.EndTiem == null).ToString());
            Console.WriteLine("p2.EndTiem == null," + (p2.EndTiem == null).ToString());
            Console.WriteLine("p1.EndTiem == DateTime.Parse(1976-09-09)," + (p1.EndTiem == DateTime.Parse("1976-09-09")).ToString());
            Console.WriteLine("p2.EndTiem == DateTime.Parse(1976-09-09)," + (p2.EndTiem == DateTime.Parse("1976-09-09")).ToString());

            p1.EndTiem = DateTime.Parse("2016-06-06");
            p2.EndTiem = null;
            Console.WriteLine();
            Console.WriteLine("赋值 p1.EndTiem = DateTime.Parse(2016-06-06)  p2.EndTiem = null 后:");
            Console.WriteLine("p1.EndTiem == null," + (p1.EndTiem == null).ToString());
            Console.WriteLine("p2.EndTiem == null," + (p2.EndTiem == null).ToString());
            Console.WriteLine("p1.EndTiem == DateTime.Parse(2016-06-06)," + (p1.EndTiem == DateTime.Parse("2016-06-06")).ToString());
            Console.WriteLine("p2.EndTiem == DateTime.Parse(2016-06-06)," + (p2.EndTiem == DateTime.Parse("2016-06-06")).ToString());     

            Console.ReadKey();
        }

    }
}

View Code

 

 

改换关键字:operator、explicit与implicit解析资料:http://www.cnblogs.com/hunts/archive/2007/01/17/operator_explicit_implicit.html

世家还可以够玩出更多的花头!!!

 

本文已联合至《C#基础知识巩固体系

ABAP CDS视图

在普通的ABAP
CDS视图开发过程中,我们经过编辑器(经常是ADT)在ABAP层阐明了俺们的字段结构和annotations。激活后,系统会自动地在数量库层生成所有的SQL视图。

图片 20

ABAP
CDS视图提供多种SQL命令和函数的支撑,假如你想要精通细节和成套的可用特性,指出您看这篇小说:ABAP
CDS Feature
Matrix

ABAP CDS Table Function

在ABAP CDS Table
Function的支付进程中,我们将字段结构、参数(可选)、association等通过类/方法定义为实体。通过AMDP大家得以平昔在ABAP层写存储过程,并且把它封装在类/方法中,更多介绍能够看前边的稿子:ABAP中的AMDP(ABAP-Managed
Database Procedures

图片 21

因为AMDP直接运行数据库脚本,所以需要做多少个附加的步骤并且会利用到脚本语言(在HANA中即SQL
Script)。稍后在示范部分大家会谈谈安排的底细。

经过上文介绍的这二种开发技术,我们可以起来开发一个技艺演示了。按本文的例证做下去,你将会得以创设你自己的ABAP
CDS Table Function
,并且为不可能一贯通过ABAP
CDS实现的需求提供解决方案。为了实现示例,大家会利用数据库视图SFLIGHTS,这一视图提供了航班连接的细节。

场景

各样航空公司提供世界上不同城市的航班连接,用户想要在单一字段中看出某一特定航空公司扶助的兼具城市,内容以逗号分隔。因为每家航空集团的城市数是不同的,大家需要一个逻辑来拼接城市们,无论有查询结果多少条数据。

在例行的ABAP
CDS内大家得以应用CONCAT函数,不过拔取它的时候,我们需要定义固定数量的字段,既然CDS视图无法兑现此处需要的处理动态逻辑,要如何处理吧?

这是一个施用ABAP CDS Table
Function的绝佳场景,因为我们可以利用简便的数据库函数STRING_AGG(String
Aggregation)。这个职能在SQL Script中可用,不过近期仍旧不匡助ABAP
CDS视图。

开发

打开你的HANA Studio(或者ADT),创立一个新的Core Data Service(Service)s ->
Data Definitio。

选料project,package并且定义名字和讲述:

图片 22

采取传输请求,然后点击Next。在模板中甄选最后一个挑选“Define Table
Function with Parameters”,然后点击Finish:

图片 23

 编辑生成的实体,包含以下内容:

  • 字段:
    • Client
    • Airline Code
    • Airline Name
    • Cities To
  • :
    ZCL_FLIGHTS_DEMO_CDS
  • 方法:
    FLIGHTS_CONNECTIONS

结果应当是:

define table function ZDEMO_FLIGHTS_TABLE_FUNCTION
returns
{
  client       : abap.clnt;
  airline_code : s_carr_id;
  airline_name : s_carrname;
  cities_to    : abap.string;
}
implemented by method
  ZCL_FLIGHTS_DEMO_CDS=>FLIGHTS_CONNECTIONS;

 当然,现在ZCL_FLIGHTS_DEMO_CDS还不存在。下一步,让大家成立它:

图片 24

让类包含IF_AMDP_MARKER_HDB接口。这一步会把您的ABAP类转换为IntelP类,并且同目的在于类的章程内写存储过程。

  PUBLIC SECTION.
    INTERFACES if_amdp_marker_hdb.

在章程实现中大家需要引入某些配置选项:

  • BY DATABASE FUNCTION: 会将艺术标记为table
    function,还有一个精选是经过 BY DATABASE
    PROCEDURE
    标记为存储过程.
  • FOR HDB: 设定数据库类型为HDB (HANA数据库).
  • LANGUAGE SQLSCRIPT: HANA数据库存储的语言.
  • OPTIONS READ-ONLY: 存储过程内不容许修改数据.
  • USING: 定义table
    function中消费的多少库表、视图或者存储过程。在本例中,只访问SFLIGHTS
    视图.

    METHOD flights_connections

    BY DATABASE FUNCTION
    FOR HDB
    LANGUAGE SQLSCRIPT
    OPTIONS READ-ONLY
    USING sflights.
    
    <<你的代码>>
    

    ENDMETHOD.

让大家准备好查询分割逻辑的六个SELECT语句。

第一个SLECT需要取得Client, Airline Code, Airline Name和City
To字段,并通过DISTINCT关键字去重,因为我们会找到在不同的连续日期的同等的宇航公司的城市记录,如图:

图片 25

英特尔P的优点之一是您可以将SELECT的查询结果传输至“内表”,并且可以执行新的SELECT来读取它的数目。让我们利用这一功力的长处,并且将率先个SELECT的语句的询问结果命名为itab_cities.

    itab_cities =
      SELECT DISTINCT 
             sflights.mandt    as client,
             sflights.carrid   as airline_code,
             sflights.carrname as airline_name,
             sflights.cityto   as city_to
        FROM sflights;

在其次个SELECT中,我们要从itab_cities中读取数据并且实现数据库方法STRING_AGG来聚合六个城市和飞行集团。为了兑现这一效益我们需要基于Client,Airline
Code和Name字段GROUP BY条目。写法是:

    RETURN
      SELECT client,
             airline_code,
             airline_name,
             STRING_AGG(city_to, ', ' ORDER BY city_to) as cities_to
        FROM :itab_cities
       GROUP BY client,
                airline_code,
                airline_name;

注意:table
function应永久有重返参数,所以记着在最后一个SELECT语句前放一个RETURN语句。此外,注意大家将字段名转换为前文中ABAP
CDS Table
Function注明的字段名,假如你从未提供一个确切的别名,激活的时候编译器会付给提醒。

 

ZCL_FLIGHTS_DEMO_CDS的终极版本是如此的:

CLASS zcl_flights_demo_cds DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    INTERFACES if_amdp_marker_hdb.

    CLASS-METHODS:
      flights_connections FOR TABLE FUNCTION zdemo_flights_table_function.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_flights_demo_cds IMPLEMENTATION.

  METHOD flights_connections
    BY DATABASE FUNCTION
    FOR HDB
    LANGUAGE SQLSCRIPT
    OPTIONS READ-ONLY
    USING sflights.

    itab_cities =
      SELECT DISTINCT 
             sflights.mandt    as client,
             sflights.carrid   as airline_code,
             sflights.carrname as airline_name,
             sflights.cityto   as city_to
        FROM sflights;

    RETURN
      SELECT client,
             airline_code,
             airline_name,
             STRING_AGG(city_to, ', ' ORDER BY city_to) as cities_to
        FROM :itab_cities
       GROUP BY client,
                airline_code,
                airline_name;

  ENDMETHOD.

ENDCLASS.

在Data Preview中的结果:

图片 26

 

英文原文:Concatenate multiple records in a single field using ABAP CDS
Table
Function

有一定量改动

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图