sql server 数组_如何在SQL Server中实现类似数组的功能

sql server 数组

介绍 (Introduction)

I was training some Oracle DBAs in T-SQL and they asked me how to create arrays in SQL Server.

我在T-SQL中培训了一些Oracle DBA,他们问我如何在SQL Server中创建阵列。

I told them that there were no arrays in SQL Server like the ones that we have in Oracle (varray). They were disappointed and asked me how was this problem handled.

我告诉他们,SQL Server中没有像Oracle( varray )中那样的数组。 他们感到失望,问我该问题如何处理。

Some developers asked me the same thing. Where are the arrays in SQL Server?

一些开发人员问我同样的事情。 SQL Server中的数组在哪里?

The short answer is that we use temporary tables or TVPs (Table-valued parameters) instead of arrays or we use other functions to replace the used of arrays.

简短的答案是我们使用临时表或TVP(表值参数)而不是数组,或者使用其他函数来替换数组。

The use of temporary tables, TVPs and table variables is explained in another article:

另一篇文章中说明了临时表,TVP和表变量的使用:

In this article, we will show:

在本文中,我们将显示:

  • How to use a table variable instead of an array

    如何使用表变量而不是数组
  • The function STRING_SPLIT function which will help us to replace the array functionality

    函数STRING_SPLIT函数将帮助我们替换阵列功能
  • How to work with older versions of SQL Server to handle a list of values separated by commas

    如何使用旧版本SQL Server处理以逗号分隔的值列表

Requirements

要求

  1. SQL Server 2016 or later with SSMS installed

    安装了SSMSSQL Server 2016或更高版本
  2. The Adventureworks database installed

    已安装Adventureworks数据库

入门 (Getting started)

How to use a table variable instead of an array

如何使用表变量而不是数组

In the first demo, we will show how to use a table variable instead of an array.

在第一个演示中,我们将展示如何使用表变量而不是数组。

We will create a table variable using T-SQL:

我们将使用T-SQL创建一个表变量:

DECLARE @myTableVariable TABLE (id INT, name varchar(20))
insert into @myTableVariable values(1,'Roberto'),(2,'Gail'),(3,'Dylan')
select * from @myTableVariable

We created a table variable named myTableVariable and we inserted 3 rows and then we did a select in the table variable.

我们创建了一个名为myTableVariable的表变量,并插入了3行,然后在该表变量中进行了选择。

The select will show the following values:

选择将显示以下值:

Now, we will show information of the table Person.person of the adventureworks database that match with the nameS of the table variable:

现在,我们将显示与表变量的nameS匹配的Adventureworks数据库的表Person.person的信息:

DECLARE @myTableVariable TABLE (id INT, name varchar(20))
insert into @myTableVariable values(1,'Roberto'),(2,'Gail'),(3,'Dylan')
 
SELECT  [BusinessEntityID]
      ,[PersonType]
      ,[NameStyle]
      ,[Title]
      ,[FirstName]
      ,[MiddleName]
      ,[LastName]
 
  FROM [Adventureworks].[Person].[Person] where 
  FirstName
  IN (Select name from @myTableVariable)

The results will display the names and information of the table Person.person with the names of Roberto, Gail and Dylan:

结果将显示表Person.person的名称和信息,表名为Roberto,Gail和Dylan:

Note that in SQL Server, it is better to use SQL sentences to compare values. It is more efficient. We do not use loops (WHILE) in general because it is slower and it is not efficient.

请注意,在SQL Server中,最好使用SQL语句比较值。 效率更高。 通常,我们不使用循环(WHILE),因为它速度较慢且效率不高。

You can use the id to retrieve values from a specific row. For example, for Roberto, the id is 1 for Dylan the id is 3 and for Gail the id is 2.

您可以使用ID从特定行中检索值。 例如,对于Roberto,ID为1,对于Dylan,ID为3,对于Gail,ID为2。

In C# for example if you want to list the second member of an array, you should run something like this:

例如,在C#中,如果要列出数组的第二个成员,则应运行以下命令:

Array[1];

You use the brackets and the number 1 displays the second number of the array (the first one is 0).

使用方括号,数字1显示数组的第二个数字(第一个为0)。

In a table variable, you can use the id. If you want to list the second member (id=2) of the table variable, you can do something like this:

在表变量中,可以使用id。 如果要列出表变量的第二个成员(id = 2),则可以执行以下操作:

DECLARE @myTableVariable TABLE (id INT, name varchar(20))
insert into @myTableVariable values(1,'Roberto'),(2,'Gail'),(3,'Dylan')
select * from @myTableVariable where id=2

In other words, you can use the id to get a specific member of the table variable.

换句话说,您可以使用id获取表变量的特定成员。

The problem with table variables is that you need to insert values and it requires more code to have a simple table with few rows.

表变量的问题在于,您需要插入值,并且需要更多的代码才能创建具有少量行的简单表。

In C# for example, to create an array, you only need to write the elements and you do not need to insert data into the table:

例如,在C#中,要创建一个数组,只需编写元素,而无需在表中插入数据:

string[] names = new string[] {"Gail","Roberto","Dylan"};

It is just a single line of code to have the array with elements. Can we do something similar in SQL Server?

使数组包含元素只是一行代码。 我们可以在SQL Server中做类似的事情吗?

The next solution will help us determine this

下一个解决方案将帮助我们确定这一点

The function STRING_SPLIT function

函数STRING_SPLIT

Another solution is to replace arrays with the use of the new function STRING_SPLIT. This function is applicable in SQL Server 2016 or later versions and applicable in Azure SQL.

另一种解决方案是使用新功能STRING_SPLIT替换阵列。 此功能适用于SQL Server 2016或更高版本,适用于Azure SQL。

If you use the function in an old adventureworks database or in SQL Server 2014 or older, you may receive an error message. The following example will try to split 3 names separated by commas:

如果在旧的Adventureworks数据库或SQL Server 2014或更早版本中使用该功能,则可能会收到错误消息。 以下示例将尝试分割3个名称,并用逗号分隔:

SELECT value FROM STRING_SPLIT('Roberto,Gail,Dylan', ',');

A typical error message would be the following:

典型的错误消息如下:

Msg 208, Level 16, State 1, Line 8
Invalid object name ‘STRING_SPLIT’

消息208,第16级,状态1,第8行
无效的对象名称“ STRING_SPLIT”

If you receive this error in SQL Server 2016, check your database compatibility level:

如果在SQL Server 2016中收到此错误,请检查数据库兼容性级别:

SELECT compatibility_level  
FROM sys.databases WHERE name = 'AdventureWorks';  
GO

If your compatibility level is lower than 130, use this T-SQL sentence to change the compatibility level:

如果您的兼容性级别低于130,请使用以下T-SQL语句更改兼容性级别:

ALTER DATABASE [Adventureworks] SET COMPATIBILITY_LEVEL = 130

If you do not like T-SQL, you can right click the database in SSMS and go to options and change the compatibility level:

如果您不喜欢T-SQL,则可以右键单击SSMS中的数据库,然后转到选项并更改兼容性级别:

The T-SQL sentence will convert the values separated by commas in rows:

T-SQL语句将转换用逗号分隔的行中的值:

SELECT value FROM STRING_SPLIT('Roberto,Gail,Dylan', ',');

The values will be converted to rows:

这些值将转换为行:

In the STRING_SPLIT function, you need to specify the separator.

在STRING_SPLIT函数中,您需要指定分隔符。

The following query will show the information of people in the person.person table that matches the names used in the STRING_SPLIT function:

以下查询将在person.person表中显示与STRING_SPLIT函数中使用的名称匹配的人员信息:

SELECT  [BusinessEntityID]
      ,[PersonType]
      ,[NameStyle]
      ,[Title]
      ,[FirstName]
      ,[MiddleName]
      ,[LastName]
 
  FROM [Adventureworks].[Person].[Person] where 
  FirstName
  IN (SELECT value FROM STRING_SPLIT('Roberto,Gail,Dylan', ','));

The query will show information about the people with the names equal to Roberto or Gail or Dylan:

该查询将显示有关姓名等于Roberto或Gail或Dylan的人员的信息:

If you want to retrieve a specific member of the string, you can assign a row # to each member row of the STRING_SPLIT. The following code shows how retrieve the information

如果要检索字符串的特定成员,可以将行#分配给STRING_SPLIT的每个成员行。 以下代码显示了如何检索信息

WITH fakearray AS  
(  
SELECT 
  ROW_NUMBER() OVER(ORDER BY value DESC) AS ID,value FROM STRING_SPLIT('Roberto,Gail,Dylan', ',')
)   
SELECT ID, value  
FROM fakearray  
WHERE ID =3

ROW_NUMBER is used to add an id to each name. For example, Roberto has the id =1, Gail id=2 and Dylan 3.

ROW_NUMBER用于为每个名称添加一个ID。 例如,Roberto的ID为= 1,盖尔的ID为2,而Dylan为3。

Once you have the query in a CTE expression, you can do a select statement and use the WHERE to specify an ID. In this example, the query will show Dylan information (ID=3). As you can see, to retrieve a value of a specific member of the fake array is not hard, but requires more code than a programming language that supports arrays.

在CTE表达式中查询后,就可以执行select语句并使用WHERE指定ID。 在此示例中,查询将显示Dylan信息(ID = 3)。 如您所见,要检索假数组的特定成员的值并不难,但是与支持数组的编程语言相比,它需要更多的代码。

How to work with older versions of SQL Server

如何使用旧版本SQL Server

STRING_SPLIT is pretty helpful, but how was it handled in earlier versions?

STRING_SPLIT非常有用,但是在早期版本中如何处理?

There are many ways to solve this, but we will use the XML solution. The following example will show how to show the values that match the results of a fake vector:

有很多方法可以解决此问题,但是我们将使用XML解决方案。 以下示例将显示如何显示与伪向量的结果匹配的值:

DECLARE @oldfakearray VARCHAR(100) = 'Roberto,Gail,Dylan';
DECLARE @param XML;
 
SELECT @param = CAST('<i>' + REPLACE(@oldfakearray,',','</i><i>') + '</i>' AS XML)
 
 
SELECT  [BusinessEntityID]
      ,[PersonType]
      ,[NameStyle]
      ,[Title]
      ,[FirstName]
      ,[MiddleName]
      ,[LastName]
 
  FROM [Adventureworks].[Person].[Person] 
  WHERE FirstName IN 
  (SELECT x.i.value('.','NVARCHAR(100)') FROM @param.nodes('//i') x(i))

The code will do the same that the STRING_SPLIT or the table variable solution:

该代码与STRING_SPLIT或表变量解决方案的作用相同:

In the first line, we just create a new fake array named oldfakearray and assign the names in the variable:

在第一行中,我们仅创建一个名为oldfakearray的新伪数组,并在变量中分配名称:

DECLARE @oldfakearray VARCHAR(100) = 'Roberto,Gail,Dylan';

In the second line, we are declaring an XML variable:

在第二行中,我们声明一个XML变量:

DECLARE @param XML;	

In the next line, we are removing the comma and creating a XML with the values of the oldfakearray:

在下一行中,我们将删除逗号,并使用oldfakearray的值创建XML:

SELECT @param = CAST('&lt;i&gt;' + REPLACE(@oldfakearray,',','&lt;/i&gt;&lt;i&gt;') + '&lt;/i&gt;' AS XML)

Finally, we are doing a select from the table Person.Person in the Adventureworks database where the firstname is in the @param variable:

最后,我们从Adventureworks数据库中的Person.Person表中进行选择,其中名字在@param变量中:

SELECT  [BusinessEntityID]
      ,[PersonType]
      ,[NameStyle]
      ,[Title]
      ,[FirstName]
      ,[MiddleName]
      ,[LastName]
 
  FROM [Adventureworks].[Person].[Person] 
  WHERE FirstName IN 
  (SELECT x.i.value('.','NVARCHAR(100)') FROM @param.nodes('//i') x(i))

As you can see, it is not an array, but it helps to compare a list of values with a table.

如您所见,它不是数组,但是有助于将值列表与表进行比较。

结论 (Conclusion)

As you can see, SQL Server does not include arrays. But we can use table variables, temporary tables or the STRING_SPLIT function. However, the STRING_SPLIT function is new and can be used only on SQL Server 2016 or later versions.

如您所见,SQL Server不包含数组。 但是我们可以使用表变量,临时表或STRING_SPLIT函数。 但是,STRING_SPLIT函数是新功能,只能在SQL Server 2016或更高版本上使用。

If you do not have SQL Server, there were older methods to split strings separated by commas. We show the method using XML files.

如果您没有SQL Server,则可以使用较旧的方法来分割用逗号分隔的字符串。 我们展示了使用XML文件的方法。

翻译自: https://www.sqlshack.com/implement-array-like-functionality-sql-server/

sql server 数组

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页