mssql查詢某個值存在某個表里的哪個字段的值里面


第一步:創建 查詢某個值存在某個表里的哪個字段的值里面 的存儲過程
create proc spFind_Column_In_DB 
( 
    @type int,--類型:1為文字類型、2為數值類型 
    @str nvarchar(100)--需要搜索的名字 
) 
as
    --創建臨時表存放結果 
    create table #tbl(PK int identity primary key ,tbl sysname,col sysname) 
    declare @tbl nvarchar(300),@col sysname,@sql nvarchar(1000) 
    if @type=1  
    begin
        declare curTable cursor fast_forward 
        for 
            select '['+SCHEMA_NAME(SCHEMA_ID)+'].['+o.name+']' tableName,'['+c.name+']' columnName from sys.columns c inner join sys.objects o on c.object_id=o.object_id 
            where o.type_desc='user_table' and user_type_id in (167,175,231,239,35,99) 
    end
    else
    begin 
        declare curTable cursor fast_forward 
        for 
        select '['+SCHEMA_NAME(SCHEMA_ID)+'].['+o.name+']' tableName,'['+c.name+']' columnName from sys.columns c inner join sys.objects o on c.object_id=o.object_id 
            where o.type_desc='user_table' and user_type_id in (56,48,52,59,60,62,106,108,122) 
    end
    open curtable 
    fetch next from curtable into @tbl,@col 
    while @@FETCH_STATUS=0 
    begin
        set @sql='if exists (select * from '+@tbl+' where '
        if @type=1 
        begin
            set @sql += @col + ' like ''%'+@str +'%'')'
        end
        else 
        begin
            set @sql +=@col + ' in ('+@str+'))'
        end
  
        set @sql += ' INSERT #TBL(tbl,col) VALUES('''+@tbl+''','''+@col+''')'
        --print @sql 
        exec (@sql) 
        fetch next from curtable into @tbl,@col 
    end
    close curtable  
    deallocate curtable 
    select * from #tbl

可能和它一起用的SQL語句:
查看與某一個表相關的視圖、存儲過程、函數
select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like '%表名%'


數據加密

防止開發人員獲取到敏感數據(SQL Server的數據加密簡介)
背景
有時候,我們還真的會碰到這樣的需求:防止開發人員獲取到敏感數據。也許你覺得很簡單,把開發和運營分開不就可以了嗎?是的,如果公司有專門的運營團隊的話,但對於很多小公司來說,幾個人的開發團隊就兼顧了需求分析、設計、開發、測試、調試、部署和運營了,數據庫密碼知道,程序代碼全有,怎么辦?——必須對數據庫里的數據進行加密,這是唯一的辦法。

也許你還是不明白,什么東西需要瞞着我們了不起的程序員,好吧,我直說了:工資!假如你的公司讓你做一個工資系統,你會不會有這方面的顧慮,一旦工資信息被公開,后果必定是很嚴重的,也許老板對你很信任,認為讓你知道沒什么問題,但其他開發人員呢?后來接手你的工作的人呢?所以必須考慮這個問題。而且,還外帶一個需求:員工自己可以用自己的“薪資查看密碼”來查看自己的工資(只能看自己的),每個人自己的“薪資查看密碼”都不一樣。另外不需要描述的隱藏需求還有:將來必定是要對薪資做統計做報表的。

相關代碼
SQL Server(2005及之后的版本)提供了內置的加密機制,加密方式有兩大類,一類是對稱加密,另一類則是非對稱加密。

SQL Server的對稱加密示例代碼:

復制代碼
--創建一個對稱密鑰,其實只需要創建一次,不用每次都創建,這個對稱密鑰密碼為123456(嗯,大多數人認為的密碼),密碼是nvarchar類型的
CREATE SYMMETRIC KEY my_symetric_key WITH ALGORITHM = DESX ENCRYPTION BY PASSWORD = N'123456';

--使用一個對稱密鑰前必須打開它,而且要提供創建它時所使用的密碼,密碼不對的話就會打開失敗
OPEN SYMMETRIC KEY my_symetric_key DECRYPTION BY PASSWORD = N'123456';

--只能加密字符串,如果要加密數字,就用CONVERT函數先把數字轉為字符串
DECLARE @strClearText NVARCHAR(100);
SET @strClearText = N'3000.00';

--密文類型為VARBINARY,用
DECLARE @strCipherText VARBINARY(MAX);
SET @strCipherText = EncryptByKey(Key_GUID('my_symetric_key'), @strClearText);

--顯示密文(密文其實為二進制格式,你會看到其HEX文本)
SELECT @strCipherText AS [密文];

--解密不需要提供密鑰名稱,SQL Server會根據當前上下文去尋找打開的對稱密鑰
DECLARE @strDecrypted VARBINARY(MAX);
SET @strDecrypted = DecryptByKey(@strCipherText);

--顯示出解密后的明文
SELECT Convert(NVARCHAR(100), @strDecrypted) AS [解密后的明文]

--關閉這個密鑰
CLOSE SYMMETRIC KEY my_symetric_key;

--以后還需要用這個密鑰的話就不用刪掉它
DROP SYMMETRIC KEY my_symetric_key;
復制代碼
SQL Server的非對稱加密示例代碼:

復制代碼
--創建一個非對稱密鑰(不用每次都創建),這個對稱密鑰密碼為123456,使用RSA512算法,另外還有RSA1024和RSA2048,強度更高,可加密內容更長,密鑰生成速度也會慢不少,RSA512這里足夠用了
CREATE ASYMMETRIC KEY my_asymetric_key WITH ALGORITHM = RSA_512 ENCRYPTION BY PASSWORD = N'123456';

DECLARE @strClearText NVARCHAR(100);
SET @strClearText = N'3000.00';

--加密,和對稱加密不一樣,不需要提供密碼,也不需要打開密鑰
DECLARE @strCipherText VARBINARY(MAX);
SET @strCipherText = EncryptByAsymKey(AsymKey_ID('my_asymetric_key'), @strClearText);

--顯示密文
SELECT @strCipherText AS [密文];

--解密,必須提供生成密鑰時候的密碼,密碼不正確的話就會出錯
--密鑰選擇不正確的話會得到NULL結果
DECLARE @strDecrypted VARBINARY(MAX);
SET @strDecrypted = DecryptByAsymKey(AsymKey_ID('my_asymetric_key'), @strCipherText, N'123456');

--顯示出解密后的明文
SELECT Convert(NVARCHAR(100), @strDecrypted) AS [解密后的明文]

--以后還需要用這個密鑰的話就不用刪掉它
DROP ASYMMETRIC KEY my_Asymetric_key;
復制代碼
另外可能用得到的一些語句有:

--查看所有對稱密鑰
SELECT * FROM sys.symmetric_keys;

--查看所有非對稱密鑰
SELECT * FROM sys.asymmetric_keys;
例子
可能你還想說:其實這些加密程序也能做,為什么要用DBMS的功能來做?——方便。前面也提到了,工資這個東西將來一定要做統計,做報表的,如果用DBMS的功能來做,一個報表也許也就是一個連表查詢的SELECT語句,但用程序來做這種“連表查詢”的功能恐怕就很麻煩了。

在應付這次需求上面,我認為比較適合用非對稱加密,即:誰都可以加密,但只有知道私鑰的人才能解密。例如我是工資管理員,我要給員工007設置工資為3000,我就用007的公鑰對“3000”進行加密好了,這樣,007能夠用自己的私鑰解密出自己的工資了,每個員工都有不同的公私鑰,都只能查看自己的工資,那問題來了,對於我這個管理員來說,要查看所有員工的工資,豈不是要知道他們全部的私鑰才行?這樣豈不是很麻煩?是的,我這次是用了一點“數據冗余”來解決這個麻煩,即:用兩列來保存工資信息,其中一列是真正的工資加密信息(amount),另一列是給員工自己查看的工資信息(amount_view),amount_view是用amount生成的,amount的內容使用工資管理員的公鑰進行加密,而amount_view的內容則使用員工的各自的公鑰進行加密。

現在我們來實踐一下:

復制代碼
--創建一個員工表
CREATE TABLE hr_emp(
emp_no nvarchar(20) PRIMARY KEY,
name_c nvarchar(20) NOT NULL,
has_salary_pwd bit NOT NULL DEFAULT(0),
);

--創建一個工資表
CREATE TABLE hr_salary(
sal_id int PRIMARY key IDENTITY(1,1) NOT NULL,
emp_no nvarchar(20) NOT NULL,
type nvarchar(15) NOT NULL,
amount varbinary(max) NOT NULL,
amount_view varbinary(max) NOT NULL
);

--增加一個外鍵約束
ALTER TABLE hr_salary ADD CONSTRAINT fk_salary_emp_ref_emp FOREIGN KEY (emp_no) REFERENCES hr_emp(emp_no);

--創建一個非對稱密鑰
CREATE ASYMMETRIC KEY salary_mgr_key
WITH ALGORITHM = RSA_512
ENCRYPTION BY PASSWORD = N'123456';

--初始化一些數據
insert into hr_emp (emp_no, name_c) values ('0008', '張三');
insert into hr_emp (emp_no, name_c) values ('0053', '李四');
insert into hr_emp (emp_no, name_c) values ('0055', '王五');
insert into hr_emp (emp_no, name_c) values ('0058', '趙六');

insert into hr_salary (emp_no, type, amount, amount_view) values('0008', 'Cash', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),8000.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0053', 'Cash', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),4000.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0055', 'Cash', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),3000.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0058', 'Cash', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),4500.00)), 0);

insert into hr_salary (emp_no, type, amount, amount_view) values('0008', 'Allowance', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),1234.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0053', 'Allowance', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),800.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0055', 'Allowance', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),765.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0058', 'Allowance', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),980.00)), 0);

insert into hr_salary (emp_no, type, amount, amount_view) values('0008', 'Deduct', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),0.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0053', 'Deduct', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),-440.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0055', 'Deduct', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),0.00)), 0);
insert into hr_salary (emp_no, type, amount, amount_view) values('0058', 'Deduct', EncryptByAsymKey(AsymKey_ID('salary_mgr_key'), Convert(nvarchar(100),0.00)), 0);
復制代碼
現在來看hr_salary表中的內容的話,發現amount列是加密的,沒有密碼就沒法知道其中的內容:

OK,我們現在來解密:

select emp_no , type , Convert ( decimal( 16 ,2 ), Convert( nvarchar (100 ), DecryptByAsymKey (AsymKey_ID ( 'salary_mgr_key'), amount, N'123456')))as amount from hr_salary;
結果出來了,解密成功。

統計各個員工工資總數,並把中文名帶出來:

select e.emp_no, e.name_c, s.amount from hr_emp e left join
(select emp_no, sum(Convert(decimal(16,2),Convert(nvarchar(100), DecryptByAsymKey(AsymKey_ID('salary_mgr_key'), amount, N'123456')))) as amount from hr_salary group by emp_no) s on e.emp_no=s.emp_no;
沒有壓力,對吧。

注意事項
至於amount_view這列的處理,大家想想也知道,方法其實前面都給出了,用CREATE ASYMMETRIC KEY語句來給每個用戶創建密鑰,密鑰名稱可以使用“ak+工號”這種規則,密碼可以用隨機生成,將密碼告訴用戶,讓他們自己記住,這樣就OK了。只是處理的時候必須記得,amount發生變化的時候,amount_view也要跟着發生變化。

用戶提供的密碼是否正確可以這樣驗證:

SELECT count(DECRYPTBYASYMKEY(AsymKey_ID('salary_mgr_key'), '', N'123456')) FROM sys.asymmetric_keys WHERE name='salary_mgr_key';
若結果為1則正確,若結果為0或出現異常則不正確。

修改密碼是很麻煩的事情,相當於重新創建一對非對稱密鑰,你得把整個加密好的數據用舊的密鑰解密好,再用新的密鑰加密。

最后還必須強調一點:整個服務器程序都不要保存密碼,否則前功盡棄,密碼必須由用戶在使用的時候提供,並且只暫存於Session中,Session丟失的話必須要求用戶重新輸入密碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM