SQL Server 批量创建作业(备份主分区)
一、 需求背景
在我的数据库实例中,有很多类似下图所示的数据库,这些数据库的名称是有规律的,每个数据库包含的表都是相同的,其中2个表是类似流水记录的表,表的数据量会比较大,占用的空间有几十G到上百G不等,这2个表相对于其它的配置表来说是比较不重要的。
现在有一个需求就是对数据库进行备份,允许丢失这两个表的数据,保留重要的配置表数据,你是否遇到过同样的问题呢?这个时候你会怎么做呢?你有什么方案呢?有什么方法可以快速备份这些数据库呢?
(Figure1:数据库列表)
阅读本文之前你可以先参考:SQL Server 游标运用:批量备份数据库
二、 案例分析
通过上面的描述,其中很重要的一点就是每个数据库中有2个大表,而且这些数据是不重要的,那么我们对这2个大表做表分区,把大数据放到其它文件组中,只留重要的配置表在主文件组(PRIMARY)中,接着就可以对主文件组进行备份,这样既满足了备份重要表数据,而且不会造成备份文件过大、占用磁盘空间、备份时间过长等问题。
方案一:
使用维护计划;请参考:SQL Server 维护计划备份主分区,只要在【执行T-SQL语句】的任务中使用循环递归所有数据库进行备份,在【清除历史记录】任务和【清除维护】任务中选择父目录就可以了;
方案二:
方案一中通过维护计划生成的作业是看不到具体的备份代码的,所以方案二就是为了补充方案一的。如果你没有作业执行时间的特殊要求,你可以创建一个作业,循环数据库名称进行主分区的备份,只是把维护计划【执行T-SQL语句】的内容放到了作业中;
这个方案有以下几个缺点:
a) 没有办法单独控制某个数据库备份的时间;
b) 数据库一多的话,在Job的Message里面没有办法显示那么多的信息;
c) 备份串行执行的,没有办法进行并行备份;
d) 个个数据库的备份不是单独的,如果作业出错,会造成后面的数据库无法备份;
e) 貌似是先写入内存,等作业完成后才一次性写入硬盘的?当数据库备份文件比较大的时候会莫名只备份几个数据库作业就退出了,没有查明是什么原因;
具体的操作步骤可以参考:SQL Server 批量备份数据库(主分区),这个方案最终的作业形式为:
(Figure2:作业列表)
方案三:
方案三是为了控制备份的时间而准备的,就是每个数据库都创建一个作业,这样的好处是可以充分的控制到每个数据库,因为我们可以需要对某个数据库进行完整备份,而且备份的粒度也有可能不同(重要客户的备份粒度会更小)
(Figure3:作业列表)
既然我们选择了方案三,那我们如何快速(批量)创建这些作业呢?我们先以数据库Barefoot.Opinion.9197为例,创建出一个作业的模板后,通过修改、替换这个作业的代码来实现批量生成新的可执行的作业脚本;
通过下面的几个步骤你就可以批量的生成备份作业:
1) 备份主分区完整备份的SQL代码(备份配置表);备份主分区差异备份的SQL代码(减轻备份文件空间压力)
2) 自动删除备份文件的SQL代码;(保证磁盘有足够空间)
3) 批量创建文件夹;(每个数据库单独一个文件夹)
4) 批量创建作业方案;(每个作业的名称、目录都不相同)
5) 批量修改作业计划的时间;(均衡分配作业的执行时间)
6) 批量删除作业;(方便维护)
7) 查看作业的执行情况;(防止作业时间过长,过长可以考虑预警)
三、 实现代码
(一) 下面的代码实现了主分区完整备份和主分区差异备份,当是星期一的深夜的时候,我们做完整备份,如果是其它时候我们就做差异备份,具体是什么时候,这个就通过计划里面的时候来控制了(计划的执行时间为星期一、星期三、星期五,这就代表星期一深夜做了完整备份、星期三和星期五分别做了差异备份)。
生成的备份文件名为:(这样的文件名方便阅读;而且能精确到秒,重复的几率不大)
DBName _Primary_Full_2013_01_14_002007.bak
DBName_Primary_Diff_2013_01_16_002034.bak

- --1设置完整模式
- USE [master]
- GO
- ALTER DATABASE [DBName.9197] SET RECOVERY FULL WITH NO_WAIT
- GO
- --2备份主分区
- DECLARE @CurrentTime VARCHAR(50), @FileName VARCHAR(200)
- SET @CurrentTime = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR, GETDATE(), 120 ),'-','_'),' ','_'),':','')
- IF(DATEPART(DW, GETDATE()) = 2)--星期一
- BEGIN
- --完整备份
- SET @FileName = 'E:\DBBackup\DBName.9197\DBName.9197_Primary_Full_' + @CurrentTime+'.bak'
- BACKUP DATABASE [DBName.9197]
- FILEGROUP='PRIMARY' TO DISK=@FileName WITH FORMAT
- END
- ELSE
- BEGIN
- --差异备份
- SET @FileName = 'E:\DBBackup\DBName.9197\DBName.9197_Primary_Diff_' + @CurrentTime+'.bak'
- BACKUP DATABASE [DBName.9197]
- FILEGROUP='PRIMARY' TO DISK=@FileName WITH DIFFERENTIAL,FORMAT
- END
- GO
- --3设置简单模式
- USE [master]
- GO
- ALTER DATABASE [DBName.9197] SET RECOVERY SIMPLE WITH NO_WAIT
- GO

(二) 下面的代码实现了删除备份文件,从下面的代码中可以看出删除了14天之前的备份文件;

- --删除之前的备份文件
- DECLARE @DeleteDate DATETIME
- SET @DeleteDate = DATEADD(DAY, -14, GETDATE())
- EXECUTE MASTER.SYS.XP_DELETE_FILE
- 0,
- N'E:\DBBackup\DBName.9197\',
- N'bak',
- @DeleteDate

(三) 下面的代码实现了批量创建文件夹,需要开启xp_cmdshell开关,使用了游标循环数据库名进行创建文件夹;

- --批量创建文件夹
- EXEC sp_configure 'show advanced options', 1
- RECONFIGURE
- EXEC sp_configure 'xp_cmdshell', 1
- RECONFIGURE
- DECLARE @DBName VARCHAR(100)
- DECLARE @SQL VARCHAR(1000)
- DECLARE CurDBName CURSOR FOR
- SELECT name FROM sys.databases WHERE name LIKE '%Opinion%' AND STATE =0
- OPEN CurDBName
- FETCH NEXT FROM CurDBName INTO @DBName
- WHILE @@FETCH_STATUS = 0
- BEGIN
- SET @SQL = 'mkdir E:\DBBackup\' + @DBName
- EXEC xp_cmdshell @SQL
- FETCH NEXT FROM CurDBName INTO @DBName
- END
- CLOSE CurDBName
- DEALLOCATE CurDBName
- EXEC sp_configure 'show advanced options', 0
- RECONFIGURE
- EXEC sp_configure 'xp_cmdshell', 0
- RECONFIGURE

(四) 下面的代码实现了批量创建作业,这里有一个创建作业的模板:JobTemplet.sql,我写了一个Replaced.bat的批处理文件,这个批处理文件替换模板文件中数据库的字符串,并生成创建新数据库作业的SQL脚本,创建之后就会执行这个SQL脚本来创建作业;
1. 使用上面提供的SQL代码,创建好作业的步骤和计划,再使用SSMS生成创建作业的脚本,这个就是JobTemplet.sql;

- USE [msdb]
- GO
- /****** 对象: Job [Barefoot_Opinion_9565] 脚本日期: 01/06/2013 14:07:27 ******/
- BEGIN TRANSACTION
- DECLARE @ReturnCode INT
- SELECT @ReturnCode = 0
- /****** 对象: JobCategory [Database Maintenance] 脚本日期: 01/06/2013 14:07:27 ******/
- IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'Database Maintenance' AND category_class=1)
- BEGIN
- EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'Database Maintenance'
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- END
- DECLARE @jobId BINARY(16)
- EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'DBName_9565',
- @enabled=1,
- @notify_level_eventlog=0,
- @notify_level_email=0,
- @notify_level_netsend=0,
- @notify_level_page=0,
- @delete_level=0,
- @description=N'备份主分区',
- @category_name=N'Database Maintenance',
- @owner_login_name=N'oofraBnimdA_gz', @job_id = @jobId OUTPUT
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- /****** 对象: Step [Bakcup] 脚本日期: 01/06/2013 14:07:27 ******/
- EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Bakcup',
- @step_id=1,
- @cmdexec_success_code=0,
- @on_success_action=3,
- @on_success_step_id=0,
- @on_fail_action=2,
- @on_fail_step_id=0,
- @retry_attempts=0,
- @retry_interval=0,
- @os_run_priority=0, @subsystem=N'TSQL',
- @command=N'--1设置完整模式
- USE [master]
- GO
- ALTER DATABASE [DBName.9565] SET RECOVERY FULL WITH NO_WAIT
- GO
- --2备份主分区(完整备份)
- DECLARE @CurrentTime VARCHAR(50), @FileName VARCHAR(200)
- SET @CurrentTime = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR, GETDATE(), 120 ),''-'',''_''),'' '',''_''),'':'','''')
- IF(DATEPART(DW, GETDATE()) = 2)--星期一
- BEGIN
- SET @FileName = ''E:\DBBackup\DBName.9565\DBName.9565_Primary_Full_'' + @CurrentTime+''.bak''
- BACKUP DATABASE [DBName.9565]
- FILEGROUP=''PRIMARY'' TO DISK=@FileName WITH FORMAT
- END
- ELSE
- BEGIN
- SET @FileName = ''E:\DBBackup\DBName.9565\DBName.9565_Primary_Diff_'' + @CurrentTime+''.bak''
- BACKUP DATABASE [DBName.9565]
- FILEGROUP=''PRIMARY'' TO DISK=@FileName WITH DIFFERENTIAL,FORMAT
- END
- GO
- --3设置简单模式
- USE [master]
- GO
- ALTER DATABASE [DBName.9565] SET RECOVERY SIMPLE WITH NO_WAIT
- GO
- ',
- @database_name=N'DBName.9565',
- @flags=0
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- /****** 对象: Step [Delete] 脚本日期: 01/06/2013 14:07:27 ******/
- EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Delete',
- @step_id=2,
- @cmdexec_success_code=0,
- @on_success_action=1,
- @on_success_step_id=0,
- @on_fail_action=2,
- @on_fail_step_id=0,
- @retry_attempts=0,
- @retry_interval=0,
- @os_run_priority=0, @subsystem=N'TSQL',
- @command=N'--删除之前的备份文件
- DECLARE @DeleteDate DATETIME
- SET @DeleteDate = DATEADD(DAY, -14, GETDATE())
- EXECUTE MASTER.SYS.XP_DELETE_FILE
- 0,
- N''E:\DBBackup\DBName.9565\'',
- N''bak'',
- @DeleteDate',
- @database_name=N'DBName.9565',
- @flags=0
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'Plan',
- @enabled=1,
- @freq_type=8,
- @freq_interval=34,
- @freq_subday_type=1,
- @freq_subday_interval=0,
- @freq_relative_interval=0,
- @freq_recurrence_factor=1,
- @active_start_date=20130105,
- @active_end_date=99991231,
- @active_start_time=10000,
- @active_end_time=235959
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- COMMIT TRANSACTION
- GOTO EndSave
- QuitWithRollback:
- IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
- EndSave:

2. 把下面的代码保存为Replaced.bat文件,这个批处理文件接受两个参数,一个是@OldStr一个是@NewStr,即旧的数据库名和新的数据库名;

- @if "%1"=="" goto error_parm
- @if "%2"=="" goto error_parm
- @echo off
- setlocal enabledelayedexpansion
- set file=E:\DBBackup\JobTemplet.sql
- set "file=%file:"=%"
- for %%i in ("%file%") do set file=%%~fi
- echo.
- set replaced=%1
- echo.
- set all=%2
- for /f "delims=" %%i in ('type "%file%"') do (
- set str=%%i
- set "str=!str:%replaced%=%all%!"
- echo !str!>>"%file%"_%2.sql
- )

3. 到这里我们已经有JobTemplet.sql和Replaced.bat文件了,我们再创建一个Replaced_Test.bat批处理进行测试,这个批处理设置两个变量,一个是@OldStr一个是@NewStr,再调用Replaced.bat来替换字符串;
- @set temp1=9565
- @set temp2=9001
- call Replaced_2.bat %temp1%,%temp2%
通过上面3个步骤,创建了3个文件,如下图所示:
(Figure4:创建的模板和批处理文件)
4. 下面的SQL代码就是使用游标的形式,循环符合条件的数据库,使用批处理替换模板文件,生成新的T-SQL文件,再执行新生成的T-SQL文件,这样就创建了游标当前数据库的备份作业了:

- -- =============================================
- -- Author: <听风吹雨>
- -- Blog: <http://gaizai.cnblogs.com/>
- -- Create date: <2013/12/03>
- -- Description: <批量创建作业的T-SQL文件(替换字符串),并执行这个T-SQL文件>
- -- =============================================
- --开启高级功能
- EXEC sp_configure 'show advanced options', 1
- RECONFIGURE
- EXEC sp_configure 'xp_cmdshell', 1
- RECONFIGURE
- DECLARE @DBName VARCHAR(100)--数据库名称
- DECLARE @CmdFile VARCHAR(1000)--创建File的Cmd命令字符串
- DECLARE @CmdJob VARCHAR(1000)--执行Job的Cmd命令字符串
- DECLARE @OldStr varchar(100)--需要替换的字符串
- DECLARE @NewStr varchar(100)--替换成字符串
- SET @OldStr = ''
- --查找符合条件的数据库
- DECLARE CurDBName CURSOR FOR
- SELECT name FROM sys.databases WHERE name LIKE '%Opinion%' AND STATE =0
- OPEN CurDBName
- FETCH NEXT FROM CurDBName INTO @DBName
- WHILE @@FETCH_STATUS = 0
- BEGIN
- --使用批处理替换模板文件,生成新的T-SQL文件
- SET @NewStr = SUBSTRING(@DBName,LEN('DBName.')+1,LEN(@DBName))
- SET @CmdFile = 'E:\DBBackup\Replaced.bat ' + @OldStr + ' ' + @NewStr
- PRINT @CmdFile
- EXEC xp_cmdshell @CmdFile
- --执行新生成的T-SQL文件
- SET @CmdJob = 'sqlcmd -i"E:\DBBackup\JobTemplet.sql _'+@NewStr+'.sql"'
- PRINT @CmdJob
- EXEC xp_cmdshell @CmdJob
- --循环下一个数据库
- FETCH NEXT FROM CurDBName INTO @DBName
- END
- CLOSE CurDBName
- DEALLOCATE CurDBName
- --关闭高级功能
- EXEC sp_configure 'xp_cmdshell', 0
- RECONFIGURE
- EXEC sp_configure 'show advanced options', 0
- RECONFIGURE

上面的脚本中你需要注意两点,如下图所示:“bat”字符串后面是有一个空格的,如果没有这个空格就会报错的;另外一点就是“sql”字符串与“_”之间也是有个空格的,这个空格是因为在使用Replaced.bat批处理创建文件的文件名的时候多一个空格(暂时还没找出原因),所以这里的文件名称需要加一个空格;
(Figure5:SQL代码)
执行完上面的脚本之后,在E:\DBBackup的目录下会生成下图所示的SQL脚本文件:
(Figure6:生成的SQL脚本文件)
(五) 到这里,SSMS中已经创建了10个作业,就如下图所显示:
(Figure7:创建的作业列表)
但是为了能分散作业的执行时间,我们有两种方式做到这点:
1) 在JobTemplet.sql中有一个参数@active_start_time=10000,这个参数的意思是在深夜1点钟的时候执行作业,所以可以在Replaced.bat这个批处理再加一个参数,并且在JobTemplet.sql中替换成我们想要的值,在外层T-SQL调用Replaced.bat的时候记录这个值,并传入到Replaced.bat中(这就留给读者自己实现吧,我只实现了下面的第二种方法);
2) 修改已经创建作业的执行时间,下面的代码实现了批量修改作业的执行时间,使用游标的形式,循环调用msdb.dbo.sp_update_schedule修改作业的执行时间;

- USE [msdb]
- GO
- -- =============================================
- -- Author: <听风吹雨>
- -- Blog: <http://gaizai.cnblogs.com/>
- -- Create date: <2013/12/03>
- -- Description: <批量修改Job备份时间>
- -- =============================================
- DECLARE @DBName VARCHAR(100)
- DECLARE @ScheduleId INT
- DECLARE @Date DATETIME
- DECLARE @Time VARCHAR(50)
- DECLARE @SQL VARCHAR(1000)
- SET @Date = '2013-01-08 00:20:00.000'
- DECLARE CurDBName CURSOR FOR
- SELECT name,schedule_id FROM SYSJOBS AS J
- LEFT JOIN [SYSJOBSCHEDULES] AS S
- ON J.job_id= S.job_id
- WHERE NAME LIKE 'DBName_%' ORDER BY NAME
- OPEN CurDBName
- FETCH NEXT FROM CurDBName INTO @DBName,@ScheduleId
- WHILE @@FETCH_STATUS = 0
- BEGIN
- --修改作业的执行时间
- SET @Time = REPLACE(CONVERT(VARCHAR, @Date, 8 ),':','')
- SET @SQL = 'EXEC msdb.dbo.sp_update_schedule
- @schedule_id = ''' + CONVERT(VARCHAR(50),@ScheduleId) + ''',
- @active_start_time=' + @Time
- PRINT(@DBName +':'+ @SQL)
- EXEC(@SQL)
- --递增分钟
- SET @Date = DATEADD(mi,20,@Date)
- --Get Next DataBase
- FETCH NEXT FROM CurDBName INTO @DBName,@ScheduleId
- END
- CLOSE CurDBName
- DEALLOCATE CurDBName

(六) 下面的代码实现了批量删除作业,使用游标的形式,循环调用sp_delete_job;

- USE [msdb]
- GO
- -- =============================================
- -- Author: <听风吹雨>
- -- Blog: <http://gaizai.cnblogs.com/>
- -- Create date: <2013/12/03>
- -- Description: <批量删除Job>
- -- =============================================
- DECLARE @DBName VARCHAR(100)
- DECLARE CurDBName CURSOR FOR
- SELECT name FROM msdb.dbo.sysjobs
- OPEN CurDBName
- FETCH NEXT FROM CurDBName INTO @DBName
- WHILE @@FETCH_STATUS = 0
- BEGIN
- --删除Job
- exec sp_delete_job @job_name = @DBName
- --Get Next DataBase
- FETCH NEXT FROM CurDBName INTO @DBName
- END
- CLOSE CurDBName
- DEALLOCATE CurDBName

(七) 查看作业的运行情况;

- --查询作业的执行情况
- SELECT b.name,b.enabled,b.description,b.date_created,b.date_modified,
- a.step_id,a.step_name,message,run_date,run_time,run_duration
- FROM [msdb].dbo.[sysjobhistory] AS a
- LEFT JOIN [msdb].[dbo].[sysjobs] AS b
- ON a.job_id = b.job_id
- ORDER BY name

(Figure8:作业执行情况)

- --查询作业与计划的对应关系
- SELECT J.name,schedule_id
- FROM [msdb].[dbo].[sysjobs] AS J
- LEFT JOIN [msdb].[dbo].[sysjobschedules] AS S
- on J.job_id= S.job_id
- WHERE J.name LIKE '%' ORDER BY J.name

(Figure9:作业与计划的对应关系)
在表[msdb].[dbo].[sysschedules]中也同样包含作业计划信息;
(Figure10:sysschedules信息)
四、 主分区完整、差异还原
既然做了上面主文件组的备份,当然我们需要去测试这个主文件组的还原了,这样才可以当遇到问题可以快速还原备份文件,达到还原数据的目的;
接下来会在另外一篇文章里面专门讲解;
五、 参考文献
sp_update_schedule (Transact-SQL)
-------------------华丽分割线-------------------
作者:听风吹雨
版权:本文版权归作者和博客园共有
转载:欢迎转载,必须保留原文链接
格言:不喜欢是因为你不会 && 因为会所以喜欢
-------------------华丽分割线-------------------
SQL Server 批量创建作业(备份主分区)的更多相关文章
- 使用SQL Server Management Studio 创建作业备份数据库
在项目中,经常需要备份数据库,如果能做到只需点个按钮(“开始备份数据库”按钮),然后什么都不管,数据库就自动备份好了,或者服务器上的数据库隔一段时间自动备份一次,那该多好啊. Sql server 的 ...
- SQL Server 批量主分区备份(Multiple Jobs)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 方案一(Solution One) 方案二(Solution Two) ...
- SQL Server 批量主分区备份(One Job)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 实现代码(SQL Codes) 主分区完整.差异还原(Primary B ...
- SQL Server 批量完整备份
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 实现方式一(One) 实现方式二(Two) 实现方式三(Thr ...
- 数据库SQL Server 2014 设置自动备份(维护计划和作业)
前言 1.SQL Server数据库自动备份可以有两种操作 第一种是在SQL控制台下的服务器名称展开,展开“管理”--选择“维护计划”,右键“新建维护计划”即可. ...
- SQL Server 维护计划实现数据库备份(Step by Step)(转)
SQL Server 维护计划实现数据库备份(Step by Step) 一.前言 SQL Server 备份和还原全攻略,里面包括了通过SSMS操作还原各种备份文件的图形指导,SQL Server ...
- SQL Server 维护计划实现数据库备份(Step by Step)
转自:http://www.cnblogs.com/gaizai/archive/2011/11/18/2254445.html 一.前言 SQL Server 备份和还原全攻略,里面包括了通过SSM ...
- sql server维护解决方案(备份、检查完整性、索引碎片整理)
请务必看原文 原文:https://ola.hallengren.com/frequently-asked-questions.html 经常问的问题 入门 如何开始使用SQL Server维护解决方 ...
- SQL Server 2017搭建主从备份
SQL Server 2017搭建主从¶ 关于日志传输¶ 和Oracle DG,Mysql主从一样,SQL Server也支持主从的高可用.进一步提高数据的安全性和业务的高可用.通过将主库上的日志传输 ...
随机推荐
- JAVA项目中的常用的异常处理情况总结
可能遇见的异常或错误: 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的.例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略. 运行时异常: ...
- 支付宝支付之扫码支付(电脑网站支付)、H5支付(手机网站支付)相关业务流程分析总结
前言 在上一篇文章<微信支付之扫码支付.公众号支付.H5支付.小程序支付相关业务流程分析总结>中,分析和总结了微信支付相关支付类型的业务流程,这里作为与微信支付平起平坐不相伯仲的支付宝支付 ...
- SpringBoot项目多模块打包与部署【pom文件问题】
[bean的pom] [user的pom] 特别注意,user模块因为有返回jsp页面和web相关,所以需要加入web依赖. chapter23 com.yuqiyu 1.0.0 4.0.0 com. ...
- TextEdit不能空验证设置
在工具箱中找到dxValidationProvider控件拖拉到界面上,添加代码 ConditionValidationRule notEmptyValidationRule = new Condit ...
- 【JavaWeb】之Servlet
一.Servlet简介 1.1 什么是Servlet(server applet): 是一种独立于平台和协议的服务器端Java应用程序,通过Servlet可以生成动态web页面.还可以在服务器端对客户 ...
- Python 正则表达式Ⅳ
repl 参数是一个函数 以下实例中将字符串中的匹配的数字乘以 2: 执行输出结果为: re.compile 函数 compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象 ...
- AngularJS 前端 MVC 的设计与搭建
代码 #未引入MVC框架之前的代码 <!doctype html> <html> <head> <meta charset="UTF-8" ...
- Maven 在 pom.xml 文件中配置 repositories 仓库
如果你希望在你的项目中使用独立的 repositories . 例如,你希望配置使用自己的 https://maven.ossez.com/repository/internal 作为仓库. 例如,修 ...
- 在vue中如何安装使用Vant
---恢复内容开始--- Vant中文文档地址:https://youzan.github.io/vant-weapp 1.创建Vue项目之后,运行安装命令:13:47:04 npm i vant - ...
- oracle中更新关键字merge和 with as关键字
merge是oracle特有的语句,两表关联操作(增.删.改)就效率非常高 merge into table_name alias1 using (table|view|sub_query) alia ...