如何从SharePoint Content DB中查询List数据

SharePoint用来维护基础数据非常方便,只需要建立自定义列表,然后使用InfoPath自定义一下维护界面,就可以实现在线的增删改查,开发效率很高。如果维护的数据需要进行审批,还可以加入工作流功能。使用SharePoint Designer可以快速开发出简单的工作流,如果是很复杂的工作流,那么就需要使用VS进行开发了。现在数据已经维护进了SharePoint List,那么怎么从数据库中将维护的数据查询出来呢?

SharePoint 的列表数据都存储在Content DB中,其中最最重要的表就是[dbo].[AllUserData],这个表中的一行数据就对应SharePoint List中的一条数据。下面介绍下如何从Content DB中查询出List数据。

Case 1简单数据类型的自定义列表查询

假设我们现在有一个Country列表,记录了全球200多个国家和地区的中文名,英文名,建国日期,面积,人口等信息,整个列表只有字符串、日期、数字等简单类型,没有User,Lookup等数据类型,则整个List的数据都可以从[dbo].[AllUserData]查询获得,具体查询步骤:

1. 查询[dbo].[AllLists]找到ListId。

 

由于整个网站集都是共用一个Content DB数据库,所以可能会出现在多个网站中都创建了Country这个List的情况,那么就会返还多条结果,这个情况下,就需要关联AllWebs表,根据网站的Url来判断到底哪个ListId才是我们需要的。

<pre class="csharpcode"><span class="kwrd">select w.FullUrl,l.tp_ID
<span class="kwrd">from [dbo].[AllLists] l
<span class="kwrd">inner <span class="kwrd">join [dbo].[AllWebs] w
<span class="kwrd">on l.tp_WebId=w.Id
<span class="kwrd">where l.tp_Title = <span class="str">'Country'

在找到了ListId后,接下来所有查询都会用到这个Id。

2. 查询[dbo].[AllUserData],找到需要查询的列,并命名为别名。

假设第一步我们查询出来的ListId是,那么我们查询Country这个列表的所有数据的SQL就是:

<pre class="csharpcode"><span class="kwrd">SELECT *
<span class="kwrd">FROM AllUserData
<span class="kwrd">where tp_ListId=<span class="str">'F20E316B-EA24-4164-9437-BBB17C182691'

这个表的列非常多,在SharePoint 2013的环境中会更多,但是存储数据的列都是用“数据类型+数字”来命名的。所以如果要找建国日期这个字段对应的列,那么就去看datetime1 datetime2等,如果要找面积,人口等数值类型的列,那就去看float1 float2等;如果要找中文名,英文名之类的字符串列,那就要看nvarchar1 nvarchar3等列。这里基本上都是靠眼睛来看的,根据查询的结果推断哪些字段存储了哪些数据。在得知每个字段的对应后,即可修改查询,将别名加上。

<pre class="csharpcode"><span class="kwrd">SELECT d.nvarchar1 <span class="kwrd">as ChineseName,d.nvarchar3 <span class="kwrd">as EnglishName,d.datetime1 <span class="kwrd">as FoundingDate,d.float1 <span class="kwrd">as Area,d.float2 <span class="kwrd">as Population
<span class="kwrd">FROM AllUserData d
<span class="kwrd">where tp_ListId=<span class="str">'F20E316B-EA24-4164-9437-BBB17C182691'

【注意:SharePoint并没有在数据库中以很方便的结构展现哪些列表字段对应哪个数据库字段,在AllLists表中,虽然有个字段tp_Fields,但是在SharePoint2010及之后,该字段是压缩的二进制,使用SQL是无法读取的。所以根本不可能通过查询数据库得知哪个字段的别名是什么。】参考:

3. 过滤掉已删除的数据。

如果数据经过删除,然后又重新录入,那么我们就会发现,第2步的查询结果会把删除的和重新录入的数据都查询出来。SharePoint采用的删除方法都是软删除,通过设置一个标志位来表示一条数据已经被删除,所以我们只需要将删除标识tp_DeleteTransactionId=0添加到where条件中,即可将未删除的数据返回。

<pre class="csharpcode"><span class="kwrd">SELECT d.nvarchar1 <span class="kwrd">as ChineseName,d.float2 <span class="kwrd">as Population
<span class="kwrd">FROM AllUserData d
<span class="kwrd">where tp_ListId=<span class="str">'F20E316B-EA24-4164-9437-BBB17C182691' <span class="kwrd">and d.tp_DeleteTransactionId=0

4. 过滤掉历史版本的数据。

如果这个列表开启了版本控制,那么我们查询的结果可能包含多个版本的数据,而我们只需要最新版本的数据,不希望历史版本数据出现在查询中。AllUserData表中,使用tp_IsCurrentVersion字段来标识这条数据是最新的当前版本还是历史版本。

于是,查询最新版本的SQL改为:

<pre class="csharpcode"><span class="kwrd">SELECT d.nvarchar1 <span class="kwrd">as ChineseName,d.float2 <span class="kwrd">as Population
<span class="kwrd">FROM AllUserData d
<span class="kwrd">where tp_ListId=<span class="str">'F20E316B-EA24-4164-9437-BBB17C182691' <span class="kwrd">and d.tp_DeleteTransactionId=0 <span class="kwrd">and d.tp_IsCurrentVersion=1

5. 过滤掉内容审批未通过的数据。

如果这个列表开启了内容审批,那么就会出现多个最新版本的情况,一个是已经被审批通过的版本,另一个是修改后还没有进行审批的版本。一般来说,我们是希望只有审批通过的才查询出来,用户进行修改后,只要审批状态不是Approve,那么就不应该出现在查询结果中。在AllUserData表中,使用tp_ModerationStatus字段来标识这行数据是否已经被审批通过。这是一个枚举类型,其值为:

0 The list item is approved.
1 The list item has been denied approval.

2 The list item is pending approval.

3 The list item is in the draft or checked out state.

4 The list item is scheduled for automatic approval at a future date.

这里,我们只要审批通过的数据,所以我们的SQL更新为:

<pre class="csharpcode"><span class="kwrd">SELECT d.nvarchar1 <span class="kwrd">as ChineseName,d.float2 <span class="kwrd">as Population
<span class="kwrd">FROM AllUserData d
<span class="kwrd">where tp_ListId=<span class="str">'F20E316B-EA24-4164-9437-BBB17C182691' <span class="kwrd">and d.tp_DeleteTransactionId=0 <span class="kwrd">and d.tp_IsCurrentVersion=1 <span class="kwrd">and tp_ModerationStatus=0

Case 2引用(Lookup)其他列表的自定义列表查询

若要将关系数据维护到SharePoint中,那么Lookup数据类型是非常常用的实现方法。使用Lookup可以很容易实现一对多和多对多关系,关于多对多关系,我们在Case3中再进行讲解,先看看一对多关系的维护与查询。

紧接着Case1,现在我们需要创建一个用户表,里面记录了用户的姓名,生日,出生国等信息,出生国字段对应的就是Lookup Country这个List,用户出生国不能乱填,必须从现有Country中进行选择,而且只能选择一个,这就是典型的一对多关系。

做过数据库设计的都应该知道,对于一对多关系,需要使用一个表添加另一个表的主键来作为外键,如果是数据库表的话,那么User表中必然有个BirthCountryId列。那么在SharePoint中,所有列表都存储在AllUserData表中,那这种关系怎么表示呢?

AllUserData表中有很多int1 int2之类的整型字段,但是这些字段并不用于存储数值类型(数值类型使用float1 float2等存储),而是用于存储Lookup表的外键。查询具有Lookup字段的自定义列表的操作如下:

1. 查询外键表。

这里Country表是User表的外键表,所以先将Country表查出来,查的字段必须包含tp_ID,这个整型主键值就是用作外键关联的。

<pre class="csharpcode"><span class="kwrd">SELECT d.tp_ID,d.nvarchar1 <span class="kwrd">as ChineseName,d.float2 <span class="kwrd">as Population
<span class="kwrd">FROM AllUserData d
<span class="kwrd">where tp_ListId=<span class="str">'F20E316B-EA24-4164-9437-BBB17C182691' <span class="kwrd">and d.tp_DeleteTransactionId=0 <span class="kwrd">and d.tp_IsCurrentVersion=1 <span class="kwrd">and tp_ModerationStatus=0

2. 查询主表。

对于我们的主表User表,查询方法跟Case1的步骤一样,找到ListId,找到需要的字段,同时需要找到外键的关联字段,也就是int1 int2这种字段。

<pre class="csharpcode"><span class="kwrd">SELECT
d.nvarchar1 <span class="kwrd">as UserChineseName,d.nvarchar3 <span class="kwrd">as UserEnglishName,d.datetime1 <span class="kwrd">as Birthdate,d.int1 <span class="kwrd">as CountryId
<span class="kwrd">FROM AllUserData d
<span class="kwrd">where tp_ListId=<span class="str">'53B70F07-3A66-4947-8560-05C5CCCE6A21' <span class="kwrd">and d.tp_DeleteTransactionId=0 <span class="kwrd">and d.tp_IsCurrentVersion=1 <span class="kwrd">and tp_ModerationStatus=0

3. Join两个查询结果。

现在看来,前两步的查询就像是两个独立的表一样了,那么接下来我们只需要把主表和外键表进行关联查询,即可。比如我们需要查询用户的姓名,生日,出生地国家中文名,那么对应的SQL就是:

dawei

【声明】:唐山站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。