前言

若你的企业使用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. RabbitMQ配置文件

    配置文件Config 在Web的可视化管理界面中可以看到一些文件的路径 比如 Config文件的地址 数据库存放的文件夹 log文件的地址 进入到这个文件夹会发现有这些文件,其中example是con ...

  2. HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)

    题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS     Memory Limit: 32768 K Description The inve ...

  3. 深入分析ConcurrentHashMap

      术语定义 哈希算法 hash algorithm 是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为哈希值. 哈希表 hash table 根据设定的哈希函数H(key)和处理冲突方 ...

  4. Loadrunner关联取参及设置检查点

    Loadrunner关联取参及设置检查点: 获取post的响应值当作参数存储,要在此post请求之上添加 web_reg_save_param("sign", "LB=m ...

  5. wpf button的mouse(leftbutton)down/up,click事件不响应解决办法

    按照WPF的帮助说明,某些控件的路由事件被内部处理了,已经被标记为Handled,自行定义的事件处理代码便不再起作用了,有时候会很郁闷!         不过WPF提供了必要的方法.         ...

  6. Android系统手机端抓包方法

    抓包准备 1. Android手机需要先获得root权限.一种是否获得root权限的检验方法:安装并打开终端模拟器(可通过安卓市场等渠道获得).在终端模拟器界面输入su并回车,若报错则说明未root, ...

  7. C++ STL中vector的内存机制和性能分析

    vecotr是动态数组,顾名思义他可以动态的增加自己的长度. 内存机制: 但是怎样的增加自己的长度? vector有两个函数一个是capacity()返回内存空间即缓冲区的大小,另一个是size()返 ...

  8. 修改MySQL的默认数据存储引擎

    因为MySQL默认的是MyISAM数据引擎,不支持事务也不支持外键,所以需要用到Innodb引擎,于是决定将mysql的默认引擎设置为innodb.1 . 查看MySQL存储引擎是用的哪个?登录MyS ...

  9. redis auth php操作

    <?php//Connecting to Redis server on localhost$redis = new Redis();$redis->connect('192.168.33 ...

  10. 10月16日上午MySQL数据库基础操作(创建、删除)

    以前用的是鼠标在界面上手动创建,这样创建会比较麻烦,而且还会经常出问题.在其它电脑上要用的话还需要重复操作.所以要使用程序代码操作,能通过代码的就不用手动操作. 在数据库界面选择要用的数据库,双击打开 ...