前言

若你的企业使用SQL Server数据库镜像为容灾技术。

那你一定做过在镜像切换之前要新建Login,而且若Login密码不同,要修改链接数据库的字符串,在切换完之后则仍需要给数据库重新赋予权限。

若真的是这样做,不仅麻烦而且业务故障时间将会拉长,我们需要做到新建的Login与之前的密码完全一样,而且可自动根据原有数据库用户链接到Login,数据库级别权限不用从新处理。

思路

有了这样的思路则Login的信息备份需要考虑两点:

1、一定要获取用户的SID,以保证镜像切换后能自动连接到login。

2、如何将二进制类型的用户密码和SID转换成字符类型存放

数据库存一个二进制为8Bit,每四位为一个16进制。8Bit二进制除以16则取得高4Bit的二进制,模以16则取低4Bit二进制。如下所示

Substring('0123456789ABCDEF',8bit / 16 + 1,1) + Substring('0123456789ABCDEF',8bit % 16 + 1,1)

脚本

通过以上想法笔者得出以下脚本:

脚本通过循环处理分析二进制的SID和PASSWORD得到相应的字符串,拼成相应login 的新建脚本,将脚本存放到指定文件下。

 CREATE PROC  [dbo].[spm_GetLoginDetails]
@loginame varchar(100)=null,
@filepath varchar(1000)=null
AS
SET NOCOUNT ON DECLARE @bin_pwd VARBINARY (8000)
DECLARE @bin_sid VARBINARY (8000)--VARBINARY密码和sid
DECLARE @string_pwd VARCHAR(8000)
SET @string_pwd=''
DECLARE @string_sid VARCHAR(8000)
SET @string_sid='' DECLARE @pwd INT,@sid INT
/*脚本存放*/
CREATE TABLE ##scriptall(id INT IDENTITY(1,1),line VARCHAR(MAX)) /*如果loginame 不存在则输出所有脚本*/
IF @loginame IS NULL
BEGIN
CREATE TABLE #temp(id INT IDENTITY(1,1),name VARCHAR(100),sid VARBINARY(256),string_pwd VARCHAR(1000),string_sid VARCHAR(1000)) INSERT INTO #temp(sid,name)
SELECT sid,name FROM sys.sql_logins DECLARE @minid INT,@maxid INT
SELECT @minid=min(id),@maxid=MAX(id) FROM #temp /*VARBINARY类型转化处理*/
WHILE (@minid<=@maxid)
BEGIN
SELECT @bin_pwd = sl.password_hash,@bin_sid=sl.sid,@string_pwd='',@string_sid=''
FROM sys.sql_logins sl join #temp t on t.sid =sl.sid
where t.id=@minid /*密码类型转化*/
SELECT @pwd = Datalength(@bin_pwd),@sid=Datalength(@bin_sid)
WHILE @pwd > 0
BEGIN
SELECT @string_pwd = Substring('0123456789ABCDEF',Substring(@bin_pwd,@pwd,1) / 16 + 1,1) +
Substring('0123456789ABCDEF',Substring(@bin_pwd,@pwd,1)%16 + 1,1) + @string_pwd
,@pwd = @pwd - 1
END
SELECT @string_pwd = ('0x' + @string_pwd) /*sid类型转化*/
WHILE @sid > 0
BEGIN
SELECT @string_sid = Substring('0123456789ABCDEF',Substring(@bin_sid,@sid,1) / 16 + 1,1) +
Substring('0123456789ABCDEF',Substring(@bin_sid,@sid,1)%16 + 1,1) + @string_sid,
@sid = @sid - 1
END
SELECT @string_sid = ('0x' + @string_sid)
UPDATE #temp SET string_pwd=@string_pwd,string_sid=@string_sid WHERE id=@minid
SET @minid=@minid+1
END
/*导出login新建脚本*/
INSERT INTO ##scriptall(line)
SELECT CASE WHEN sp.TYPE = 'S' THEN '
/****** Object: Login ['+sp.name+'] Script Date: '+convert(VARCHAR,GETDATE(),25)+' ******/
CREATE LOGIN [' + sp.name + '] WITH PASSWORD = ' + t.string_pwd + ' HASHED, SID = ' + t.string_sid + ',CHECK_POLICY = ' + CASE sl.is_policy_checked WHEN 0 THEN 'OFF'ELSE 'ON'END + ' , CHECK_EXPIRATION = ' + CASE sl.is_policy_checked WHEN 0 THEN 'OFF'ELSE 'ON'END +char(10)+CASE when s.denylogin=1 then '; DENY CONNECT SQL TO ' + QUOTENAME( sp.name ) else '' end +case when s.hasaccess=0 then '; REVOKE CONNECT SQL TO ' + QUOTENAME( sp.name ) else ''end
ELSE
'/****** Object: Login ['+sp.name+'] Script Date: '+convert(VARCHAR,GETDATE(),25)+' ******/
CREATE LOGIN [' + sp.name + '] FROM WINDOWS WITH DEFAULT_DATABASE=[' + sp.default_database_name + ']'
END
FROM sys.sql_logins sl
RIGHT JOIN sys.server_principals sp
ON sl.sid = sp.sid
JOIN sys.syslogins s
ON s.sid = sp.sid
left join #temp t on t.sid=sl.sid
WHERE sp.TYPE IN ('S','G','U') and loginname<>'sa'
ORDER BY sp.name
END
/*若存在loginame,则输出相应的脚本*/
ELSE
BEGIN IF EXISTS (SELECT TOP 1 1 FROM sys.sql_logins s WHERE s.name = @loginame)
BEGIN SELECT @bin_pwd = sl.password_hash,@bin_sid=sl.sid
FROM sys.sql_logins sl
WHERE sl.name = @loginame
SELECT @pwd = Datalength(@bin_pwd),@sid=Datalength(@bin_sid)
/*密码类型转化*/
WHILE @pwd > 0
BEGIN
SELECT @string_pwd = Substring('0123456789ABCDEF',Substring(@bin_pwd,@pwd,1) / 16 + 1,
1) + Substring('0123456789ABCDEF',Substring(@bin_pwd,@pwd,1)%16 + 1,
1) + @string_pwd,@pwd = @pwd - 1
END
SELECT @string_pwd = ('0x' + @string_pwd)
/*SID类型转化*/
WHILE @sid > 0
BEGIN
SELECT @string_sid = Substring('0123456789ABCDEF',Substring(@bin_sid,@sid,1) / 16 + 1,
1) + Substring('0123456789ABCDEF',Substring(@bin_sid,@sid,1)%16 + 1,
1) + @string_sid,@sid = @sid - 1 END
SELECT @string_sid = ('0x' + @string_sid) END
/*导出login新建脚本*/
INSERT INTO ##scriptall(line)
SELECT CASE WHEN sp.TYPE = 'S' THEN '
/****** Object: Login ['+sp.name+'] Script Date: '+convert(varchar,GETDATE(),25)+' ******/
CREATE LOGIN [' + sp.name + '] WITH PASSWORD = ' + @string_pwd + ' HASHED, SID = ' + @string_sid + ',CHECK_POLICY = ' + CASE sl.is_policy_checked WHEN 0 THEN 'OFF'ELSE 'ON'END + ' , CHECK_EXPIRATION = ' + CASE sl.is_policy_checked WHEN 0 THEN 'OFF'ELSE 'ON'END +char(10)+CASE when s.denylogin=1 then '; DENY CONNECT SQL TO ' + QUOTENAME( sp.name ) else '' end +case when s.hasaccess=0 then '; REVOKE CONNECT SQL TO ' + QUOTENAME( sp.name ) else ''end
ELSE
'/****** Object: Login ['+sp.name+'] Script Date: '+convert(varchar,GETDATE(),25)+' ******/
CREATE LOGIN [' + sp.name + '] FROM WINDOWS WITH DEFAULT_DATABASE=[' + sp.default_database_name + ']'
END
FROM sys.sql_logins sl
RIGHT JOIN sys.server_principals sp
ON sl.sid = sp.sid
JOIN sys.syslogins s
ON s.sid = sp.sid
WHERE sp.TYPE IN ('S','G','U')
AND sp.name = @loginame
END /*结果集输出*/
IF @filepath IS NULL
BEGIN
SELECT line
FROM ##scriptall
ORDER BY id ASC
DROP TABLE ##scriptall
END
ELSE
BEGIN
declare @cmd varchar(1000)
SELECT @cmd = 'master..xp_cmdshell ''bcp "select line from ##ScriptAll order by id" queryout ' + @filepath + ' -T -c -S' + @@SERVERNAME + ''''
EXEC( @cmd)
DROP TABLE ##scriptall
END

SQL Server 服务器器信息备份(一)--login新建脚本备份的更多相关文章

  1. 由于服务器意外的断电,导致SQL SERVER服务器上数据库出现“置疑”而无法使用,

    来自百度 1.停止数据库服务器,将数据库MDF文件和LDF文件复制备份一份2.启动数据库服务器,删除置疑的数据库3.仅用备份的数据库MDF文件附加数据库,sp_attach_db或者sp_attach ...

  2. 人人都是 DBA(III)SQL Server 调度器

    在 SQL Server 中,当数据库启动后,SQL Server 会为每个物理 CPU(包括 Physical CPU 和 Hyperthreaded)创建一个对应的任务调度器(Scheduler) ...

  3. SQL Server服务器名称与默认实例名不一致的修复方法

    SQL Server服务器名称与默认实例名不一致的修复方法 分类: 个人累积 SQl SERVER 数据库复制2011-08-10 09:49 10157人阅读 评论(0) 收藏 举报 sql ser ...

  4. 解决SQL Server管理器无法连接远程数据库Error: 1326错误

    解决SQL Server管理器无法连接远程数据库Error: 1326错误 我们在在使用SQL Server时都会遇到使用SQL Server Management Studio无法连接远程数据库实例 ...

  5. SQL Server 服务器磁盘测试之SQLIO篇

    原文:SQL Server 服务器磁盘测试之SQLIO篇 数据库调优工作中,有一部分是需要排查IO问题的,例如IO的速度或者RAID级别无法响应高并发下的快速请求.最常见的就是查看磁盘每次读写的响应速 ...

  6. Windows10中“SQL Server 配置管理器”哪去了?

    SQL Server 配置管理器是一种工具,用于管理与 SQL Server 相关联的服务.配置 SQL Server 使用的网络协议以及从 SQL Server 客户端计算机管理网络连接配置.SQL ...

  7. 监控目前所有连接SQL SERVER的用户信息

    原文:监控目前所有连接SQL SERVER的用户信息 if object_id('p_getlinkinfo','P')is not null drop proc p_getlinkinfo go c ...

  8. 在非SQL客户端使用命令行方式定期连接SQL Server 服务器并模拟用户查询操作,同时输出信息内容

    一个很长的标题,实现的功能就是尽量使用非人力的方式模拟人去做一件事情,为了便于记录,将他们输出成文件方便查阅. 图形界面方式,使用微软自己的ConnMaker.exe,或者Microsoft 数据连接 ...

  9. SQL Server优化器特性-隐式谓词

    我们都知道,一条SQL语句提交给优化器会产生相应的执行计划然后执行输出结果,但他的执行计划是如何产生的呢?这可能是关系型数据库最复杂的部分了.这里我为大家介绍一个有关SQL Server优化器的特性- ...

随机推荐

  1. 洛谷P1629 邮递员送信

    题目描述 有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间.这个邮递员每 ...

  2. ecshop /pick_out.php SQL Injection Vul By Local Variable Overriding

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 在进行输入变量本地模拟注册的时候,没有进行有效的GPC模拟过滤处理,导出 ...

  3. WCF入门

    一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...

  4. 同样有缓冲区,为什么bufferedReader输入流不需要清空缓冲区?而bufferedWriter需要清空缓冲区呢?

    当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取, 如果缓冲区数据不足,才会再从文件中读取.清不清空Buf ...

  5. JS-用js的for循环实现九九乘法表以及其他算数题等

    <!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>f ...

  6. SSH项目与SSM项目的进入首页的方法

    SSH项目中: jsp页面一般都是存放在WEB-INF下面的目录下,这样我们就不能直接访问到这些jsp页面了,保证了页面的安全性. 在struts的管理中,是利用action来实现页面的跳转,进入in ...

  7. 如何排查APP服务端和客户端是否支持ATS

    服务端排查 取得客户端直接连接的服务端域名及端口,例如mob.com.cn,端口443,即HTTPS默认端口.针对公网可访问的生产环境地址,建议使用的在线监测工具.https://wosign.ssl ...

  8. 10月23日上午PHP数组

    正则表达式 1.替换 $s = "hello5world"; $s = preg_replace("/\d/","#",$s); echo ...

  9. Android学习笔记——CheckBox

    该工程的功能实现在一个activity中显示一个单选框和一个多选框 以下代码是MainActivity.java文件中的代码 package com.example.checkbox; import ...

  10. 《CSS3实战》读书笔记 第三章:选择器:样式实现的标记

    第三章:选择器:样式实现的标记 选择器的魔力在于,让你完全实现对网页样式的掌控.不同的选择器可以用在不同的情况下使用.总之把握的原则是:规范的编码,根据合理地使用选择器,比去背选择器的定义有价值的多. ...