本篇文章是Integration Services系列的第十三篇,详细内容请参考原文


简介
在前一篇我们结合了之前所学的冒泡、日志记录、父子模式创建一个自定义的SSIS包日志记录模式。
在这一篇,我们将升级我们的解决方案到SQL Server 2012 Integration Services,演示SSIS变量,变量配置和表达式管理动态值。在前面的练习中我们已经使用过变量,但我们没有深入学习,这一篇,我们将关注SSIS变量。
……
Getting Starting with the Visual Studio 2012 IDE for SSIS 2012 Development
You must have SQL Server 2012 Integration Services installed to use the Visual Studio 2012 Integrated Development Environment (IDE) with SSIS 2012.你可以在这里下载VS 2012 IDE 和SSIS模板。
一旦安装好,你可以设置主题颜色,工具->选项->环境->常规,如图13.1所示:

图13.1
创建一个新SSIS解决方案和项目
为了创建一个新SSIS解决方案和项目,点击文件->新建项目。等等,你不能点击文件->新建项目,因为文件->新建项目不存在(图13.2)

图13.2
有两种方法创建:
1、你是否还记得VS中创建新项目的快捷键?许多人不知道快捷键,Ctrl+Shift+N,它依旧可以使用。
2、启动起始页。点击视图->起始页来打开起始页,如图13.3所示:

图13.3
起始页是VS启动时的欢迎页面。如果你不记得快捷键,它通常非常有用。起始页如图13.4所示:

图13.4
点击新建项目链接创建一个新SSIS项目。如果没有展开,展开左侧列表中的已安装的模板。展开模板->商业智能。在左边列表选择Integration Services,然后从模板选择Integration Services项目。命名项目为My_Second_SSIS_Project,如图13.5所示:

图13.5
你可能需要指定一个路径或接受默认路径。除非我有某些原因修改默认设置,我勾选"为解决方案创建目录",去掉"添加到源代码管理"复选框。
当你点击确定按钮,新My_Second_SSIS_Project解决方案和项目就会创建。解决方案文件夹在位置文本键入的路径下,项目文件夹在解决方案文件夹下,如图13.6所示:

图13.6
更多关于VS解决方案文件夹的内容请参考本系列的第一篇的创建Integration Services 项目章节。
SSIS2012简单介绍
SSIS2012和之前的版本有些不同。VS IDE变化显著。在开发页面有一个缩放滑块(图13.7)。左边的图片是滑块的正常外观,当鼠标移动到它上面时,它的外观如右边所示:

图13.7
缩放滑块下方的按钮是"适合的视图到窗口"按钮,它提供"自动缩放"来显示选定的选项卡的所有内容。
SSIS工具箱已经和.net控制库分离/脱钩。为了显示SSIS工具箱,请在包设计区域的右上角(左起第二个)点击SSIS工具箱图标,如图13.8所示:

图13.8
你仍然可以通过点击SSIS->变量或控制流空白区域打开SSIS变量。有一个新的按钮显示变量窗口,就在SSIS工具箱按钮的左边,如图13.9所示:

图13.9
也许SSIS2012最大的变化集中在新的部署模型:项目部署模型。项目部署是SSIS2012新引入的,但是通过项目部署模型SSIS2012支持之前版本开发的包。
在操作变量之前,让我们重命名包为VariablesAndParameters.dtsx(图13.10)

图13.10
注意:在你重命名dtsx文件时不会再提示重命名包对象。
Beginning with Variables
正如前面提到,有多种方法可以打开变量窗口。使用你喜欢的方法打开它。第一个按钮是添加变量(图13.11)

图13.11
点击添加变量按钮为SSIS包创建一个新变量。重命名它为MyVariable如图13.12所示:

图13.12
注意变量的作用域是SSIS包的名称:VariablesAndParameters.作用域的一个很好的比喻是容器。在图13.13我们看到三个容器:
->任务
->容器
->包

图13.13
任务、容器和包都是可执行文件。Among other attributes, an executable is a type of object in SSIS that has properties and raises events.一个任务通常驻留在容器内。"那如果我直接把一个执行SQL任务放到控制流呢?",包也是一个容器。SSIS还包含其他容器:序列容器、For循环容器、Foreach循环容器。每一个容器可以持有任务,每一种类型的容器都是可执行文件。
SSIS提供其他方式可视化作用域。为了演示,从SSIS工具箱添加一个序列容器到控制流,然后再添加一个执行SQL任务到序列容器,如图13.14所示:

图13.14
在包资源管理器中以树视图描述了作用域。这个寓意和图13.13代表的相同:包(VariablesAndParameters)包含容器(Sequence Container),容器包含任务(Execute SQL Task),如图13.15所示:

图13.15
The treeview helps us visualize what I mean when I say "up" or "down" in scope.从执行SQL任务的视角,序列容器是在它之上。如果从序列容器的视角,执行SQL任务是它的下面或包含在它里面。我可以说执行包任务包含在VariablesAndParameters包中,但是这个陈述忽略了序列容器,并且提供一个对包和任务之间关系不完整的描述。为了更准确我应该陈述,VariablesAndParameters包包含一个序列容器,序列容器包含一个执行SQL任务。
The scope of a variable is defined by the executable to which the variable is scoped.我们的MyVariable变量的作用域是VariablesAndParameters包范围。我有时将这些变量称做包作用域变量。
包资源管理器树视图的另一点:我相信"可执行堆栈"是一个合理的陈述。我宁愿使用"可执行树",但是这个词在SSIS中用得太多。可执行堆栈引用/代表可执行文件之间的关系。可执行文件通常从堆栈往下执行的(从包->容器->任务)。一些消息——比如第十二篇讲到的事件——是从堆栈往上执行。As you can glean from these examples, one gets a lot of use from the Package Explorer.
SSIS2012中变量默认的作用域是包范围。我们可以更改SSIS变量的作用域,但是到目前为止,我没有发现一个作用域在包级别以下的变量的好例子。通过点击变量窗口工具栏的第二个按钮,我们可以将变量移动到不同的作用域,如图13.16所示:

图13.16
选择MyVariable变量然后点击移动变量按钮,会显示选择新作用域窗口,如图13.17所示:

图13.17
可用的作用域呈树状显示,你可以选择期望的作用域点击确定按钮。为了演示,我们选择序列容器,点击确定。
注意,MyVariable变量的作用域更改为序列容器,如图13.18所示:

图13.18
在控制流,点击序列容器,然后观察变量窗口。MyVariable在变量窗口是可见的,如图13.19所示:

图13.19
现在点击控制流的空白区域,然后观察变量窗口:

图13.20
MyVariable在变量窗口不再可见。为什么?The default behavior of SSIS is to only show variables at or above the current scope."我能修改这个默认行为吗?",当然可以。点击变量窗口工具栏的第四个按钮"网格选项":

图13.21
变量的网格选项包含变量窗口的许多选项。我们勾选"显示所有作用域的变量"复选框,如图13.22所示:

图13.22
点击确定按钮返回到控制流和变量窗口。点击控制流的空白区域,注意你可以在变量窗口看到MyVariable变量,即使它的作用域在包之下(在序列容器范围):

图13.23
在SSIS以前的版本中,变量的作用域是创建变量时所选择的可执行文件。SSIS包的默认行为(现在仍然)是只在当前或以上范围显示变量。我同意变量默认是包作用域/范围,但是我不同意,因为作用域而隐藏变量。
为什么我不同意隐藏在执行堆栈下面或外部的变量?如果我意外地在低于包范围创建一个变量,我可以创建第二个变量作为补偿。这两个变量允许有相同的名称,不同的作用域,但它们不是相同的变量。
为了演示,删除执行SQL任务,并在它的位置上添加一个脚本任务。创建一个新变量MyVariable,它自动是包作用域:

图13.24
我故意给变量提供不同的默认值。
双击脚本任务打开编辑器,将ScriptLanguage属性设置为Microsoft Visual Basic 2012.点击ReadOnlyVariables属性文本框的省略号。当选择变量窗口打开时,注意列表只有一个MyVariable,如图13.25所示:

图13.25
选择MyVariable变量,点击确定按钮。脚本任务编辑器应该如图13.26所示:

图13.26
点击编辑脚本按钮,打开脚本编辑器并导航到Public Sub Main()模块。添加代码13.1到Public Sub Main()

MsgBox(Dts.Variables("User::MyVariable").Value.ToString)

代码13.1
你的脚本编辑器应该如图13.27所示:

图13.27
关闭脚本编辑器,点击脚本任务编辑器上的确定按钮。在调试器下按F5执行SSIS包。消息对话框会显示MyVariable变量的值,会显示哪个值呢?

图13.28
如果你遵循示例演练,提供给序列容器的默认值会显示。为什么是这个变量获胜?
回想一下我之前提过的执行堆栈以及思考堆栈如何传送事件从原始的可执行文件(任务、容器、包)。是否还记得怎样工作的?事件向上传送,我把这个称作事件冒泡。
变量行为以一种相似的方式。脚本任务执行前,SSIS尝试锁定MyVariable变量。如果两个可执行文件试图同一时间使用同一变量会发生什么?如果一个可执行文件在写变量的值,另一个可执行文件只是读取变量的值?为了确保变量的值保持静态(或确定),SSIS会在变量上放置一个锁,因此它的值在使用期间不能被无意操纵。
一种思考SSIS中如何锁定变量的方法是想象锁定机制(用keyholder比喻)轮询执行堆栈查找MyVariable变量。keyholder在脚本任务开始,并问它"脚本任务,你有一个MyVariable变量吗?"脚本任务回应"没有。"因此keyholder往上走一步问序列容器,"序列容器,你有一个MyVariable变量吗?"序列容器回应,"有。"keyholder停止查找。它找到了它所寻求的变量。
如果我的变量是隐藏的(所有SSIS版本默认),我可能没意识到我有两个不同作用域的MyVariable变量。我可能会设置序列容器的MyVariable,然后忘记了。之后再创建一个包范围的MyVariable变量。
另外,"显示所有作用域的变量"复选框并不会作为解决方案或项目属性的部分一直保留。当我关闭SSDT再次打开它时,这个设置恢复成默认值了。
这就是我为什么不喜欢在不同的作用域隐藏变量:在脚本任务我没有办法得到包范围的MyVariable变量。在我选择ReadOnlyVariables时它不会出现在我的列表中。我不能使用"VariablesAndParameters.User::MyVariable".这个选项不存在。并且,我不知道变量是否存在除非我打开"显示所有作用域的变量"。If the default behavior is to set all variables to package scope, the default should also be to show variables at all scopes.
变量数据类型
SSIS变量有多种数据类型:various numeric data types,date,byte,Boolean,string,and character.
最有意思的可能是Object数据类型。

图13.29
Object数据类型的变量可以持有多种值包括标量比如整数、字符串和日期。Objects还可以持有Objects:比如集合、数组、记录集和数据集。
变量值
变量窗口的"值"列显示了变量的默认值。作为实践经验,我会把默认值设置为开发SSIS包时使用的值,即使当我部署SSIS包到生产环境。这样做的原因会在之后文章解释。但是主要的原因是如果生产环境包执行时发生意外,或者某人错误的操作,我宁愿用生产数据加载我的开发环境,也不愿用开发数据加载我的生产环境。图13.30显示了我们使用的两个变量的默认值:

图13.30
变量表达式
SSIS表达式语言非常难学。个人认为它更像是curly-brace-languages(C#、Java等)和Transact-SQL的混合。如果你把SSIS定位为企事业数据集成平台,那就很适合了。
我们可以使用表达式操纵SSIS变量的值。为了演示,点击MyVariable变量表达式文本框的省略号,如图13.31所示:

图13.31
打开的表达式生成器窗口包含四部分:变量参数、表达式语言、表达式、计算结果值,如图13.32所示:

图13.32
变量和参数树视图包含所有可用的变量和参数列表。在我们的SSIS包中,在变量和参数虚拟文件夹下的唯一变量是包范围的MyVariable,如图13.33所示:

图13.33
为什么我们看不到序列容器范围的MyVariable?因为序列容器范围的MyVariable就是我们设置表达式的变量。我们如何验证呢?我们可以从变量和参数拖动MyVariable变量到表达式文本框,然后点击求值表达式按钮,如图13.34所示:

图13.34
包范围的MyVariable变量默认值是0;序列容器的MyVariable变量默认值是42。因此,前面验证是包范围的MyVariable变量。
表达式语言树视图包含SSIS表达式语言操作和函数,如图13.35所示:

图13.35
在表达式文本框中删除"@[User::MyVariable]",从日期/时间函数树节点拖动DARTPART函数到表达式文本框。在表达式文本框用"ss"替换<<datepart>>.在SSIS表达式语言树视图,点击GETDATE()函数并拖动到表达式文本框。用GETDATE()替换<<date>>。最终的表达式应该是DATEPART("ss",GETDATE())如图13.36所示:

图13.36
这个表达式会将当前时间的秒数赋值给序列容器范围的MyVariable变量。关闭表达式生成器,注意变量窗口如图13.37所示:

图13.37
注意在变量名称的旁边有一个fx图标。这表明一个表达式控制着变量的值。
我们配置的表达式出现在变量窗口的表达式列。为了演示,在SSIS调试器下按F5启动包。脚本任务会显示MyVariable变量的值的消息对话框。它是0-59之间的一个数字,当前时间的秒数,如图13.38所示:

图13.38
在我们继续之前,停止调试器,从序列容器删除脚本任务,并且删除两个MyVariable变量。
使用变量创建连接
让我们学以致用。变量可以用来生成其他变量的值。Let’s demonstrate that by using a variable to create a path to a flat file containing some data.
首先创建Songs.csv平面文件:

 Id,Artist,Song
"","Waylon Jennings","Lonesome, On'ry, and Mean"
"","Willie Nelson","Blue Eyes Cryin' in the Rain"
"","Kris Kristofferson","Sunday Mornin', Coming Down"

代码13.2
在SSDT,添加一个数据流任务到控制流,将从序列容器连接一个优先约束到数据流任务,如图13.39所示:

图13.39
打开数据流任务,添加一个平面文件源,如图13.40所示:

图13.40
打开平面文件源编辑器,通过点击右侧新建按钮创建一个新的平面文件连接管理器:

图13.41
当打开平面文件连接管理器编辑器,在"连接管理器名称"输入"Songs Flat File";"文件名"属性浏览到Songs.csv文件保存位置;"文本限定符"属性输入双引号,如图13.42所示:

图13.42
点击确定关闭平面文件连接管理器编辑器,注意Songs Flat File出现在"平面文件连接管理器"属性:

图13.43
点击确定关闭平面文件源编辑器。如果你没有一个叫做TestDB的数据库,你可以用其他数据库来测试开发,或者使用代码13.3创建TestDB库:

Use master
go
If Not Exists(Select name
From sys.databases
Where name = 'TestDB')
begin
print 'Creating TestDB'
Create Database TestDB
print 'TestDB created'
end
Else
print 'TestDB already exists'
go

代码13.3
返回到SSDT,在拖动一个OLE DB目标到数据流面板,并与平面文件源连接起来,如图13.44所示:

图13.44
打开OLE DB目标编辑器,点击"OLE DB连接管理器"下拉列表右侧的新建按钮,创建一个新的OLE DB连接管理器并打开配置OLE DB连接管理器编辑器窗口,如图13.45所示:

图13.45
点击底部的新建按钮,打开连接管理器。输入服务器名,
在"服务器名"键入你的数据库实例的名称,在"连接到一个数据库"选择或输入一个数据库名,如图13.46所示:

图13.46
点击确定关闭连接管理器窗口。配置OLE DB连接管理器窗口会显示我们的新连接——我的显示为"LUEST\SQL08R2.TestDB",如图13.47所示:

图13.47
确保数据连接中选择了你的新连接,点击确定按钮。OLE DB目标编辑器的"OLE DB连接管理器"属性中会显示我们的连接管理器。
点击"表或视图的名称"右侧的新建按钮显示创建表窗口。这个窗口显示一条DDL语句(依据数据流中的元数据生成),如图13.48所示。表名是由OLE DB目标衍生,修改它为Songs.列定义是由平面文件源和OLE DB目标之间的数据流路径确定:

图13.48
在编辑表名后,点击确定按钮。注意,点击确定按钮会在你的数据库中执行这个DDL语句。这也就是为什么新表会出现在"表或视图的名称",如图13.49所示:

图13.49
在OLE DB目标编辑器的底部,注意警告信息。这条警告信息告诉我们接下来要在映射页上映射列,但是注意确定按钮是可用的。这在SSIS2012是新引入的,It's one example of something Microsoft calls Flexible Order of Authoring or FOA.
我对FOA混杂着情绪。我在OLE DB目标中不喜欢它。为什么呢?它可能让我马上点击确定,以致在我的数据流中OLE DB目标只配置了部分。在之前的版本,是不会出现这种情况的,因为只有我们操作过映射后确定按钮才可用。然而,在我配置查找转换的时候,我很喜欢FOA。查找转换有五个页面,我讨厌要记住之前页面的操作当发生意外(比如映射失败…).FOA gives and FOA takes away.
返回到SSDT,点击OLE DB目标编辑器上的映射页。当你操作时,列就会自动映射,如图13.50所示:

图13.50
可用输入列是从数据流路径流向OLE DB目标的列。可用目标列是我们在目标中配置的表或视图的可用列。在本例中,我们前面创建的目标表,OLE DB目标从哪里获取元数据并创建那张表呢?
为了回答这个问题,首先点击确定完成OLE DB目标的配置。然后右击连接平面文件源和OLE DB目标的数据流路径,选择编辑,打开数据流路径编辑器。点击元数据页,显示数据流路径结构的属性,如图13.51所示:

图13.51
看起来是否眼熟?我认为这看起来像一个表定义。我们有列名,数据类型,长度。当我们点击OLE DB目标编辑器上的新建按钮创建表的时候,这些元数据提供了架构信息。
因为可用目标列(图13.50)中的列是由可用输入列的元数据创建,列的名称和数据类型都能匹配,因此就会出现自动映射的情况。
点击确定,关闭数据流路径编辑器。
Variables in Expressions
打开SSIS变量窗口,添加一个包范围的字符串类型的FileDirectory变量。将变量的值设置为songs.csv文件存放的文件夹,如图13.52所示:

图13.52
创建另一个包范围的字符串类型的FileName变量。设置它的值为songs.csv:

图13.53
再添加一个包范围的字符串类型的FilePath变量,如图13.54所示:

图13.54
点击FilePath变量的表达式文本框的省略号,打开表达式生成器窗口展开左上方的变量和参数虚拟文件夹。点击并拖动User::FileDirectory到表达式文本框;在变量("@[User::FileDirectory]")后面,加一个空格,然后一个加号("+")作为字符串连接操作,点击并拖动User::FileName变量到表达式文本框;点击求值表达式按钮查看表达式的值,如图13.55所示:

图13.55
哎哟,在data文件夹和Songs.csv文件名之间少了一个反斜杠。不用担心,我们可以在表达式中添加一个连接操作("+")和反斜杠来修复这个问题,如图13.56所示:

图13.56
让我们再次点击求值表达式按钮,我们看到图13.57的结果:

图13.57
表达式解析失败?错误显示在第26个字符处有问题。第26个字符是双引号中的反斜杠。为什么它会打断表达式?因为反斜杠是一个escape字符串。一个反斜杠加其他的字符表示一些特殊的文本。因此如何获取一个简单的反斜杠?使用"\\",如图13.58所示:

图13.58
点击确定,关闭表达式生成器。
Variables in Dynamic Property Expressions
我们现在有一个变量(FilePath)包含我们源文件的完整路径。FilePath变量由另外两个变量(FileDirectory、FileName)组成的表达式构建。
让我们用这个完整的路径动态的引导我们的平面文件连接管理器(Songs Flat File)到文件。
点击Songs Flat File文件连接管理器,然后按F4显示连接管理器属性(图13.59):

图13.59
点击表达式值文本框的省略号,打开属性表达式编辑器。点击属性下拉列表选择ConnectionString属性,如图13.60所示:

图13.60
点击表达式文本框的省略号打开表达式生成器。展开变量和参数树视图中的虚拟文件夹。拖动FilePath变量到表达式文本框,如图13.61所示:

图13.61
点击确定按钮,关闭表达式生成器窗口,然后点击确定按钮关闭属性表达式编辑器。如果你在属性窗口展开表达式属性,你会看到ConnectionString属性,如图13.62所示:

图13.62
引入断点和变量状态
断点用于处理故障检测,或仅仅是查看状态,在SSIS调试器执行期间。在第九篇和第十二篇讲述,SSIS使用事件/监听器模式。事件处理程序、日志记录、进度/执行结果页签,断点是事件监听器的一个例子。在这一章节,我们设置一个断点,当数据流任务引起/产生一个PreExecute事件时暂停执行。
在我们运行测试之前,返回到控制流,右击数据流任务点击"编辑断点…",如图13.63所示:

图13.63
当"设置断点-数据流任务"窗口显示,点击"当容器接收到OnPreExecute事件时断开" 中断条件,如图13.64所示:

图13.64
……
点击确定按钮关闭"设置断点-数据流任务"窗口。
数据流任务上出现一个褐红色的圆点表明断点已经设置,如图13.65所示:

图13.65
按F5启动调试器,注意数据流任务产生一个PreExecute事件时会暂停执行,并且在断点图标上出现一个黄箭头,如图13.66所示:

图13.66
为了查看FilePath变量的状态,点击菜单栏上的调试->窗口->本地,如图13.67所示:

图13.67
你也可以通过快捷键:同时Ctrl+Alt键,然后按下V键再按下L键。Pressing multiple keys in this manner is sometimes called a chord.一旦打开,展开变量节点,往下滑动直到找到User::FilePath变量,如图13.68所示:

图13.68
值列包含SSIS包此刻调试执行时的变量值。注意在FilePath和FileDirectory变量值中要用双反斜杠代表反斜杠。
按F5在调试器下执行SSIS包,包执行完成后我们就从Songs.csv文件加载了3条数据,如图13.69所示:

图13.69

-- *** Clean up ***
-- ****************
USE master;
GO
IF DB_ID('TestDB') IS NOT NULL DROP DATABASE TestDB;
GO

总结
在这一篇,我们升级解决方案到SQL Server 2012 Integration Services.我们演示了SSIS变量,变量配置和表达式管理动态值。

【译】第十三篇 Integration Services:SSIS变量的更多相关文章

  1. 第十三篇 Integration Services:SSIS变量

    本篇文章是Integration Services系列的第十三篇,详细内容请参考原文. 简介在前一篇我们结合了之前所学的冒泡.日志记录.父子模式创建一个自定义的SSIS包日志记录模式.在这一篇,我们将 ...

  2. 【译】第二篇 Integration Services:SSIS数据泵

    本篇文章是Integration Services系列的第二篇,详细内容请参考原文. 简介SSIS用于移动数据.数据流任务提供此功能.因为这个原因,当介绍SSIS时我喜欢从数据流任务开始.数据流任务的 ...

  3. 【译】第一篇 Integration Services:SSIS是什么

    本篇文章是Integration Services系列的第一篇,详细内容请参考原文. Integration Services是一种在SQL Server中最受欢迎的子系统.允许你在各种数据源之间提取 ...

  4. 【译】第九篇 Integration Services:控制流任务错误

    本篇文章是Integration Services系列的第九篇,详细内容请参考原文. 简介在前面三篇文章,我们创建了一个新的SSIS包,学习了脚本任务和优先约束,并检查包的MaxConcurrentE ...

  5. 【译】第十五篇 Integration Services:SSIS参数

    本篇文章是Integration Services系列的第十五篇,详细内容请参考原文. 简介在前一篇,我们使用SSDT-BI将第一个SSIS项目My_First_SSIS_Project升级/转换到S ...

  6. 【译】第十四篇 Integration Services:项目转换

    本篇文章是Integration Services系列的第十四篇,详细内容请参考原文. 简介在前一篇,我们查看了SSIS变量,变量配置和表达式管理动态值.在这一篇,我们使用SQL Server数据商业 ...

  7. 第十五篇 Integration Services:SSIS参数

    本篇文章是Integration Services系列的第十五篇,详细内容请参考原文. 简介在前一篇,我们使用SSDT-BI将第一个SSIS项目My_First_SSIS_Project升级/转换到S ...

  8. 第二篇 Integration Services:SSIS数据泵

    本篇文章是Integration Services系列的第二篇,详细内容请参考原文. 简介SSIS用于移动数据.数据流任务提供此功能.因为这个原因,当介绍SSIS时我喜欢从数据流任务开始.数据流任务的 ...

  9. 【译】第十二篇 Integration Services:高级日志记录

    本篇文章是Integration Services系列的第十二篇,详细内容请参考原文. 简介在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...

随机推荐

  1. ACM数论之旅16---母函数(又名生成函数)(痛并快乐着(╭ ̄3 ̄)╭)

    (前排出售零食瓜子) 前言: 母函数是个很难的东西,难在数学 而ACM中所用的母函数只是母函数的基础 应该说除了不好理解外,其他都是非常简单的 母函数即生成函数,是组合数学中尤其是计数方面的一个重要理 ...

  2. 基于JQuery的前端form表单操作

    Jquery的前端表单操作:     jquery提供了良好的方法封装,在一些基本的操作的时候,能节省很多的麻烦,其中,在具体使用时,form表单的数据提交是最频繁也最常见的前后数据交换方式,所以在前 ...

  3. java 循环时候当达到这个类型的极值时 会停止输出

  4. P3165 [CQOI2014]排序机械臂

    题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到高度最低的物品的位置 P1P_1P1​ ,并把左起第一个物品至 P1P_1P1 ...

  5. Repeats SPOJ - REPEATS(重复次数最多的连续重复子串)

    论文题例8 https://blog.csdn.net/queuelovestack/article/details/53031731这个解释很好 其实,当枚举的重复子串长度为i时,我们在枚举r[i* ...

  6. MT【121】耐克数列的估计

    已知$\{a_n\}$满足$a_1=1,a_2=2,\dfrac{a_{n+2}}{a_n}=\dfrac{a_{n+1}^2+1}{a_n^2+1}$, 求$[a_{2017}]$_____ 解:容 ...

  7. java中poi进行execl导出

    首先贴出最终导出的execl截图吧: 前台界面如下: 点击导出时,为其按钮的onclick事件添加exportDate()函数: function exportDate(){ var begin_Da ...

  8. 【CF888G】Xor-MST(最小生成树,Trie树)

    [CF888G]Xor-MST(最小生成树,Trie树) 题面 CF 洛谷 题解 利用\(Kruskal\)或者\(Prim\)算法都很不好计算. 然而我们还有一个叫啥来着?\(B\)啥啥的算法,就叫 ...

  9. Find First and Last Position of Element in Sorted Array - LeetCode

    目录 题目链接 注意点 解法 小结 题目链接 Find First and Last Position of Element in Sorted Array - LeetCode 注意点 nums可能 ...

  10. java多线程 -- 同步鎖

    为了解决多线程安全问题在 Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile .Java 5.0 后增加了一些新的机制,但并不是一种替代内置 ...