2008年12月30日 星期二

如何從作業反查DTS封裝呢

最近剛好在整理資料庫,在辨認那些排程作業的用途,有些作業的名稱與DTS封裝名稱一樣,這種不須辨認,但是有的作業名稱偏偏取的完全與DTS不一樣,點進步驟裡看,又是一串加密值的十六進位文字"DTSRun /~Z0x5E4633AE...",這以小弟智商來說絕對看不懂的,於是想到從MSDB的資料表裡去看關聯性,結果完全對不起來,上網尋尋覓覓終於找到方法了,給各位參考,不過很不實用,因為結果是產生在剪貼簿裡,剪貼簿耶,有沒有搞錯,我還得用右鍵貼上才能看到結果...@@

1.在編輯作業步驟的命令那,把整串"DTSRun /~Z0x5E4633AE..."複製下來

2.打開命令提示字元

3. 把剛剛複製的那串文字貼上去


4. 在字串的最後面加上 /!X /!C


5.如下圖那樣,執行囉



6.就會看到上圖那個什麼載入中執行中


7.此時你再貼上,就可以看到DTS封裝的名稱囉,就是上圖紅線那行,我有用藍框框起來的地方,就是DTS的封裝名稱,了解了吧

2008年12月29日 星期一

DTS執行處理序工作很遜












原以為可以執行cmd下的所有東西,包含%%這種的變數,結果不行

C:\Winnt\system32\Cmd.exe /c "rename c:\mis.txt mistt%date:~4,4%.txt"

正常執行上面那行會把mis.txt更名為mistt2008.txt
結果只能更名為mistt.txt
這樣是不是很遜?
害我得寫vbscript,要不然用cmd把檔名更名為日期格式的檔名是多麼方便的一件事啊

2008年12月26日 星期五

[函數]日期時間轉換[int2datatime]

最近在查詢sysjobhistory資料表的時候,發現其中run_date日期與run_time時間兩欄位的的資料型別都是int,要拿來跟datatime資料型別比較日期先後順序有點麻煩,上網找了找,果然在sqldev.net看到已經有高人寫好函數了,這樣我就不用自己寫啦,我改了一下內容再貼過來囉


create function [dbo].[fn_intDateTime2DateTime] (@intDate int, @intTime int)
returns datetime
as
begin
--宣告變數
declare @year int, @month int, @day int,
@hour int, @min int, @sec int
Declare @rtnDate datetime ,@strDate nvarchar(40)
--日期處理
set @year = (@intDate / 10000)
set @month = (@intDate - (@year * 10000)) / 100
set @day = (@intDate - (@year * 10000) - (@month * 100))
--時間處裡
set @hour = (@intTime / 10000)
set @min = (@intTime - (@hour * 10000)) / 100
set @sec = (@intTime - (@hour * 10000) - (@min * 100))
--格式轉換
select @strDate = convert(nvarchar(4), @year) + N'-' + convert(nvarchar(2), @month) + N'-' + convert(nvarchar(4), @day) + N' ' +
replace(convert(nvarchar(2), @hour) + N':' + convert(nvarchar(2), @min) + N':' + convert(nvarchar(2), @sec), ' ', '0')

select @rtnDate = convert(datetime, @strDate)

return @rtnDate

end




go



SELECT sysjobhistory.run_date AS 'int日期', sysjobhistory.run_time AS 'int時間' ,dbo.fn_intDateTime2DateTime(sysjobhistory.run_date,sysjobhistory.run_time)AS 'datetime時間'FROM sysjobhistory

2008年12月25日 星期四

NUL的意義與用法

NUL是一個特殊的空設備,它沒有可控制的PC硬體或埠,可以說是一種虛擬的設備吧,有點像黑洞一樣,可以吞噬任何輸入輸出之請求而不給回應,就給你隱藏起來喔!


控制碼 1 表示標準輸出;控制碼 2 表示錯誤輸出!













1.看上圖,正常執行pasue命令,會顯示"請按任意鍵繼續...",然後等待你的下一步動作
2.若在後面接 1>nul 的話,就會將標準輸出隱藏囉
3.一般的move命令,若沒有檔案可移動,則會出現錯誤輸出"系統找不到指定的檔案
4.若在後面接 2>nul 的話,就會將錯誤輸出隱藏囉。

5.當然也可以後面接1>nul 2>nul ,就表示將所有輸出都隱藏,不過這樣感覺好像病毒的行為喔,故意讓你不知在作什!


6.我個人喜歡在batch裡這樣用1>log.txt 2>err.txt,這樣就不管任何訊息都會留下記錄囉,執行結果寫到log.txt,錯誤訊息寫到err.txt,方便我後續有問題時除錯囉,給各位參考!

對了,我好像沒有提到重定向">"的意義,自行去微軟參考吧http://technet.microsoft.com/en-us/library/bb490982.aspx





2008年12月24日 星期三

模擬使用者

模擬使用者這功能還滿好用的,有時候User說他的連線帳號權限有問題,但是我不知道他的密碼怎麼辦,不就沒法用他的帳號去測試了,其實可以使用模擬使用者這功能,很方便的囉

--SQL 2000
--傳回目前使用者的名稱
select CURRENT_USER
--模擬成a這個使用者
setuser 'a'
--SELECT CURRENT_USER

--執行其他陳述式,測測這個使用者的權限或其他等等的功能囉

--切換回來
setuser

--====================================--

--SQL 2005
--傳回目前使用者的名稱
select CURRENT_USER
--模擬成a這個使用者
EXECUTE AS USER='a'
--SELECT CURRENT_USER

--執行其他陳述式,測測這個使用者的權限或其他等等的功能囉

--切換回來
REVERT

2008年12月23日 星期二

用Convert轉換日期格式(無聊版)

我把線上說明的每種格式都試了說,沒人比我更無聊吧,不過這樣比較清楚啊,呵呵!

網路上有人說這樣轉會有缺點,因為轉換後的是文字格式囉,不再是日期格式了,個人覺得還好啦!


--mon dd yyyy hh:miAM
select convert(varchar(18),getdate(),0)
select convert(varchar(18),getdate(),100)

--12 23 2008 5:10PM

--mm/dd/yy
select convert(varchar(8),getdate(),1)
--12/23/08

--mm/dd/yyyy
select convert(varchar(10),getdate(),101)
--2/23/2008

--yy.mm.dd
select convert(varchar(8),getdate(),2)
--08.12.23

--yyyy.mm.dd
select convert(varchar(10),getdate(),102)
--2008.12.23

--dd/mm/yy
select convert(varchar(8),getdate(),3)
--23/12/08

--dd/mm/yyyy
select convert(varchar(10),getdate(),103)
--23/12/2008

--dd.mm.yy
select convert(varchar(8),getdate(),4)
--23.12.08

--dd.mm.yyyy
select convert(varchar(10),getdate(),104)
--23.12.2008

--dd-mm-yy
select convert(varchar(8),getdate(),5)
--23-12-08

--dd-mm-yyyy
select convert(varchar(10),getdate(),105)
--23-12-2008

--dd mon yy
select convert(varchar(8),getdate(),6)
--23 12 08

--dd mon yyyy
select convert(varchar(10),getdate(),106)
--23 12 2008

--Mon dd, yy
select convert(varchar(9),getdate(),7)
--12 23, 08

--Mon dd, yyyy
select convert(varchar(11),getdate(),107)
--12 23, 2008

--hh:mm:ss
select convert(varchar(8),getdate(),8)
select convert(varchar(8),getdate(),108)

--17:03:08

--mon dd yyyy hh:mi:ss:mmmAM
select convert(varchar(25),getdate(),9)
select convert(varchar(25),getdate(),109)

--12 23 2008 5:06:29:093PM

--mm-dd-yy
select convert(varchar(8),getdate(),10)
--12-23-08

--mm-dd-yyyy
select convert(varchar(10),getdate(),110)
--12-23-2008

--yy/mm/dd
select convert(varchar(8),getdate(),11)
--08/12/23

--yyyy/mm/dd
select convert(varchar(10),getdate(),111)
--2008/12/23

--yymmdd
select convert(varchar(6),getdate(),12)
--081223

--yyyymmdd
select convert(varchar(8),getdate(),112)
--20081223

--dd mon yyyy hh:mm:ss:mmm(24h)
select convert(varchar(23),getdate(),13)
select convert(varchar(23),getdate(),113)

--23 12 2008 17:17:38:227

--hh:mi:ss:mmm(24h)
select convert(varchar(12),getdate(),14)
select convert(varchar(12),getdate(),114)

--17:18:43:590

--yyyy-mm-dd hh:mi:ss(24h)
select convert(varchar(19),getdate(),20)
select convert(varchar(19),getdate(),120)

--2008-12-23 17:20:32


--yyyy-mm-dd hh:mi:ss.mmm(24h)
select convert(varchar(23),getdate(),21)
select convert(varchar(23),getdate(),121)

--2008-12-23 17:22:35.763

--yyyy-mm-dd Thh:mm:ss:mmm(no spaces)
select convert(varchar(23),getdate(),126)
--2008-12-23T17:23:56.913

--有奇怪文字的
--dd mon yyyy hh:mi:ss:mmmAM
select convert(nvarchar(30),getdate(),130)--25 ذو الحجة 1429 5:26:26:067P

--年份很奇怪的
--dd/mm/yy hh:mi:ss:mmmAM
select convert(varchar(25),getdate(),131)
--25/12/1429 5:28:52:047PM

--20110725更新,不小心又發現兩種格式,已補上

Select CONVERT(varchar(20), GETDATE(), 22)
--07/25/11  8:28:22 PM

Select CONVERT(varchar(10), GETDATE(), 23)
--2011-07-25

用xcopy快速複製目錄結構

今天剛好遇到一個問題,要怎麼只複製目錄結構,而不複製檔案呢?原本是打算用dir再配合for迴圈去作,但後來發現多此一舉,用xcopy本身就可以做到了!


xcopy /T /E source destination


xcopy功能非常多呢,下面是詳細的參數,自己看吧

XCOPY source [destination] [/A /M] [/D[:date]] [/P] [/S [/E]] [/V] [/W]
[/C] [/I] [/Q] [/F] [/L] [/H] [/R] [/T] [/U]
[/K] [/N] [/O] [/X] [/Y] [/-Y] [/Z]\r\n [/EXCLUDE:file1[+file2][+file3]...]

source 指定要複製的檔案。
destination 指定位置或者/以及新檔案的名稱。
/A 只複製設定成保存屬性的檔案,不要改變屬性的設定。
/M 只複製設定成保存屬性的檔案,並清除保存屬性。
/D:m-d-y 複製在指定日期當天或之後發生變更的檔案。如果沒有給日期,
只複製那些來源檔案日期比目的檔案日期為新的檔案。
/EXCLUDE:file1[+file2][+file3]...
指定檔案清單字串。如果有字串對應到要進行複製的檔案絕對
路徑的任何部分,這個檔案會被排除複製。例如,指定字串
\obj\ 或 .obj 的話,會排除所有在 obj 目錄下副檔名是
.obj 的檔案複製。
/P 在建立每個目的檔案時顯示提示。
/S 複製每個目錄及其包含的子目錄,不複製空目錄。
/E 複製每個目錄及其包含的子目錄,也複製空目錄。/S 與 /E
相同,能夠用來修改 /T。
/V 驗證每個新檔案。
/W 在複製之前提示您按鍵繼續。
/C 如果錯誤發生時也繼續複製。
/I 如果目的不存在且複製一個以上的檔案的話,就假設指定的
目的一定是目錄。
/Q 在複製時不要顯示檔名。
/F 在複製時顯示來源及目的檔案的全部檔名。
/L 顯示要複製的檔案。
/H 時複製隱藏檔和系統檔。
/R 覆蓋唯讀檔案。
/T 建立目錄結構,但不複製其中的檔案。不包括空目錄及子目錄。
/T /E 會包括空目錄及子目錄。
/U 只複製已經存在目的位置的檔案。
/K 複製檔案屬性。通常 Xcopy 會重設唯讀的屬性。
/N 用所產生的短檔名來進行複製。
/O 複製檔案所有權及 ACL 資訊。
/X 複製檔案審查設定 (包含 /O)。
/Y 不要提示您確認是否要覆蓋一個已經存在的檔案。
/-Y 示您確認是否要覆蓋一個已經存在的檔案。
/Z 在可重新開始的模式中複製網路檔案。

參數 /Y 可以在 COPYCMD 環境變數中預先設定。但可以在指令行中用 /-Y 參數
來覆蓋原有設定。

使用sp_executesql來Create Database

因為任務需要建立20多個Database,當時就在想怎樣建立最快囉,想也知道要建很多個當然用T-SQL,不過在串接變數時發生問題,後來找到得使用sp_executesql來執行串接過的陳述式囉,如下,只要變更資料庫名稱跟磁碟名稱就好,用這樣建這樣很快囉

--2000 & 2005 適用
Declare @DBName nvarchar(20)
Declare @DBDataName nvarchar(25)
Declare @DBDataPath nvarchar(40)
Declare @DBLogName nvarchar(24)
Declare @DBLogPath nvarchar(44)
Declare @SQLcmd nvarchar(256)
Declare @DiskPath nvarchar(20)
--資料庫名稱
set @DBName = 'mis33tt'
--磁碟名稱
set @DiskPath = 'E:\'
set @DBDataName = @DBName + '_Data'
set @DBDataPath = @DiskPath + @DBDataName + '.MDF'
set @DBLogName = @DBName + '_Log'
set @DBLogPath = @DiskPath + @DBLogName + '.LDF'

set @SQLcmd = 'CREATE DATABASE ' + @DBName + ' ON (NAME = ''' + @DBDataName +
''', FILENAME = ''' + @DBDataPath + ''' , SIZE = 10, FILEGROWTH = 10%) LOG ON (NAME = ''' +
@DBLogName + ''', FILENAME = ''' + @DBLogPath + ''' , SIZE = 1, FILEGROWTH = 10%)' +
' COLLATE Chinese_Taiwan_Stroke_CI_AS'

exec sp_executesql @SQLcmd


注意: @SQLcmd 需為Unicode 字串喔,否則會出現下列錯誤
訊息 214,層級 16,狀態 2,程序 sp_executesql,行 12 程序需要有類型為 'ntext/nchar/nvarchar' 的參數 '@statement'。

2008年12月22日 星期一

帳號提升權限,原來的程式反而出現錯誤了?

先說明當時情況好了,接到一個任務,要重建一個系統的開發環境,SQL Server要獨立一台,因為需要複製二十多個資料庫,只要資料庫結構,不要資料,想說只是給測試用的,為了省時,我把新的開發環境程式用的連線帳號,權限提升到最大sysadmin,這樣權限設定就簡單許多了,結果反而程式不能跑了說,會有錯誤,而且是很簡單T-SQL喔

Select * from table2

上面這個簡單到不能在簡單了,有table2,而且使用的連線帳號已經給到sysadmin,居然會有錯誤,在原本的機器上可以跑,為什新的不行,我當時想破頭,不知為什,甚至懷疑是不是SQL版本不同造成,結果後來終於研究出來,原來是沒使用"物件擁有者.物件"所造成的,各位看看我以下的T-SQL,COPY過去使用,配合註解的說明,應該可以了解到問題在哪?

--先用系統管理員角色登入,此例為join
--假設在Northwind下有一使用者t,角色為db_owner
use northwind

--尋找目前使用者的名稱與使用者的登入識別名稱
select suser_sname() as '登入識別名稱' , user_name() as '目前使用者的名稱'
--join dbo

--建立一個owner為t的表格t1
create table t.t1(a1 int)

--使用全名
select * from t.t1
/* 正常 */
--不使用全名
select * from t1
/* 無效的物件名稱 't1' */
/*不使用全名,會先找"使用者名稱.物件",再找"dbo.物件"
兩個結果都是"dbo.物件",因為沒有dbo.t1,所以會回傳錯誤囉*/

--模擬使用者t,角色為db_owner
setuser 't'
select suser_sname() as '登入識別名稱' , user_name() as '目前使用者的名稱'
-- t t

--使用全名
select * from t.t1
/* 正常 */
--不使用全名
select * from t1
/* 正常 */
/*因為會先找"使用者名稱.物件",這個情況就會找t.t1囉,所以有找到*/

--設回原來使用者
setuser

--把t新增到 sysadmin 伺服器的固定角色內
EXEC sp_addsrvrolemember 't', 'sysadmin'

--模擬使用者t
setuser 't'

select suser_sname() as '登入識別名稱' , user_name() as '目前使用者的名稱'
/* t dbo */
/*注意使用者名稱原來是t,現已變成dbo囉,因為已是sysadmin成員之一*/

--使用全名
select * from t.t1
/* 正常 */
--不使用全名
select * from t1
/* 無效的物件名稱 't1'。 */
/*因為會先找"使用者名稱.物件",此時使用者名稱已變為dbo,
所以這個情況就會找dbo.t1囉,問題是沒有押,再找第二次也是dbo.t1,
還是沒有,所以回報錯誤囉*/

--設回原來使用者
setuser






因為table2的擁有者不是dbo,如果擁有者是dbo,一般是不需要使用 ObjectOwner.DatabaseObject 語法的;如果擁有者不是dbo,最好使用ObjectOwner.DatabaseObject 語法囉


個人覺得不管什麼情況,還是使用ObjectOwner.DatabaseObject 語法比較妥當,效率也會好點

2008年12月19日 星期五

如何保留NULL值或不保留

最近使用SSIS剛好遇到一個問題,指定遇到NULL值,如果文字欄位要變為空白,如果是數字欄位要變為0,要怎麼作呢?


1.首先建立一個table1,這是目的地的資料表,要有預設值喔,有預設值才有辦法變空白或變0或變為你想要的值



CREATE TABLE [dbo].[table1]
( [mydate] [datetime] NULL DEFAULT ('19110101'),
[myint] [int] NULL DEFAULT ((0)),
[mychar] [char](5) NULL DEFAULT (''))


2. 有個來源資料table2如下,有兩筆資料,其中第二筆資料值皆為NULL





3. 拉一個資料流程,其中來源是table2,目的地是table1,如下圖









4.先示範保留NULL值的設定,用左鍵雙按"OLE DB 目的地", [保留Null]打勾,如下圖







5.執行看看囉,結果如下,NULL值原封不動的保留囉






6.那如果在第4步驟,[保留Null]取消勾選,執行後的結果如下圖囉,你看原本NULL值的部分,都變成之前建立資料表時所設的預設值






7.SQL SERVER目的地一樣有同樣的設定喔

用vbs發信很簡單

server上不需安裝smtp服務,但你必須有一發信帳戶就可以使用這個發信囉,發信時還可附加檔案或從文字檔讀取內容喔

列出Log大小變化

執行結果如下圖



--SQL 2000適用
--在插入資料表變數時,不可使用 EXECUTE 當為來源
--所以只能實際建立資料表


create table dbo.logtable
(DBName varchar(30),
logsize float,
used float,
status bit)


insert into logtable
exec('dbcc sqlperf(logspace)')



-- 依據交易記錄檔的大小,由高到低的進行排序


SELECT DBName '資料庫', Convert( decimal(8,2),logsize) N'交易記錄檔使用的硬碟空間(MB)',
Convert( decimal(8,2),logsize*used/100) N'交易記錄檔實際的使用空間(MB)'
FROM logtable
ORDER BY 2 DESC




--SQL 2005適用
--在插入資料表變數時,不可使用 EXECUTE 當為來源(2005才能用)

DECLARE @tLogSize TABLE
(DBName sysname, logsize float, used float, status int)
INSERT into @tLogSize
exec ('DBCC SQLPERF(LOGSPACE)')


-- 依據交易記錄檔的大小,由高到低的進行排序

SELECT DBName '資料庫', Convert( decimal(8,2),logsize) N'交易記錄檔使用的硬碟空間(MB)',
Convert( decimal(8,2),logsize*used/100) N'交易記錄檔實際的使用空間(MB)'
FROM @tLogSize
ORDER BY 2 DESC

2008年12月18日 星期四

快速取得資料庫資料表結構





--適用SQL 2005,簡單列一下
select t.name as [table name], c.name AS [column name], tp.name AS [資料型別],
case tp.name
when 'bigint' then cast(c.precision as varchar(3))
when 'int' then cast(c.precision as varchar(3))
when 'smallint' then cast(c.precision as varchar(3))
when 'tinyint' then cast(c.precision as varchar(3))
when 'numeric' then '(' + cast(c.precision as varchar(3)) + ',' + cast(c.scale as varchar(3)) + ')'
when 'decimal' then '(' + cast(c.precision as varchar(3)) + ',' + cast(c.scale as varchar(3)) + ')'
when 'nvarchar' then cast((c.max_length/2) as varchar(5))
when 'nchar' then cast((c.max_length/2) as varchar(5))
else cast(c.max_length as varchar(5))
end as [長度],
CASE WHEN c.is_nullable=1 THEN 'ok' ELSE 'no' END AS [NULL ok],
ep.value as [描述]
from sys.tables as t
inner join sys.columns as c on t.object_id=c.object_id
inner join sys.types as tp on c.system_type_id = tp.system_type_id
left outer join sys.extended_properties as ep on (ep.major_id = t.object_id
and ep.minor_id = c.column_id and ep.class = 1 )
where tp.system_type_id = tp.user_type_id
order by t.name,c.name


--適用SQL 2000,我從對岸看到的,給他貼過來,對岸高手好厲害
SELECT sysobjects.name AS [table], sysproperties.[value] AS 表說明,
syscolumns.name AS field, properties.[value] AS '欄位說明', systypes.name AS type,
syscolumns.length, ISNULL(COLUMNPROPERTY(syscolumns.id, syscolumns.name,
'Scale'), 0) AS 小數位數 , syscolumns.isnullable AS isnull,
CASE WHEN syscomments.text IS NULL THEN '' ELSE syscomments.text END AS [Default],
CASE WHEN COLUMNPROPERTY(syscolumns.id, syscolumns.name, 'IsIdentity')
= 1 THEN '√' ELSE '' END AS 標識, CASE WHEN EXISTS
(SELECT 1 FROM sysobjects WHERE xtype = 'PK' AND name IN
(SELECT name FROM sysindexes WHERE indid IN
(SELECT indid FROM sysindexkeys WHERE id = syscolumns.id AND colid = syscolumns.colid)))
THEN '√' ELSE '' END AS 主鍵 FROM syscolumns INNER JOIN
sysobjects ON sysobjects.id = syscolumns.id INNER JOIN
systypes ON syscolumns.xtype = systypes.xtype LEFT OUTER JOIN
sysproperties properties ON syscolumns.id = properties.id AND
syscolumns.colid = properties.smallid LEFT OUTER JOIN
sysproperties ON sysobjects.id = sysproperties.id AND
sysproperties.smallid = 0 LEFT OUTER JOIN
syscomments ON syscolumns.cdefault = syscomments.id
WHERE (sysobjects.xtype = 'U')

Batch命令變數截取

看圖應該知道作什用的吧




下面是對岸高手製作的程式產生的,我直接把結果貼過來囉

變數var的值為: 0123456789ABCDEF

%var:~1,1% 截取之後的字元為: 1
%var:~1,5% 截取之後的字元為: 12345
%var:~1,9% 截取之後的字元為: 123456789
%var:~1,13% 截取之後的字元為: 123456789ABCD
%var:~4,1% 截取之後的字元為: 4
%var:~4,5% 截取之後的字元為: 45678
%var:~4,9% 截取之後的字元為: 456789ABC
%var:~4,13% 截取之後的字元為: 456789ABCDEF
%var:~7,1% 截取之後的字元為: 7
%var:~7,5% 截取之後的字元為: 789AB
%var:~7,9% 截取之後的字元為: 789ABCDEF
%var:~7,13% 截取之後的字元為: 789ABCDEF
%var:~10,1% 截取之後的字元為: A
%var:~10,5% 截取之後的字元為: ABCDE
%var:~10,9% 截取之後的字元為: ABCDEF
%var:~10,13% 截取之後的字元為: ABCDEF
%var:~13,1% 截取之後的字元為: D
%var:~13,5% 截取之後的字元為: DEF
%var:~13,9% 截取之後的字元為: DEF
%var:~13,13% 截取之後的字元為: DEF

%var:~1,-1% 截取之後的字元為: 123456789ABCDE
%var:~1,-4% 截取之後的字元為: 123456789AB
%var:~1,-7% 截取之後的字元為: 12345678
%var:~1,-10% 截取之後的字元為: 12345
%var:~1,-13% 截取之後的字元為: 12
%var:~5,-1% 截取之後的字元為: 56789ABCDE
%var:~5,-4% 截取之後的字元為: 56789AB
%var:~5,-7% 截取之後的字元為: 5678
%var:~5,-10% 截取之後的字元為: 5
%var:~5,-13% 截取之後的字元為:
%var:~9,-1% 截取之後的字元為: 9ABCDE
%var:~9,-4% 截取之後的字元為: 9AB
%var:~9,-7% 截取之後的字元為:
%var:~9,-10% 截取之後的字元為:
%var:~9,-13% 截取之後的字元為:
%var:~13,-1% 截取之後的字元為: DE
%var:~13,-4% 截取之後的字元為:
%var:~13,-7% 截取之後的字元為:
%var:~13,-10% 截取之後的字元為:
%var:~13,-13% 截取之後的字元為:

%var:~-2,1% 截取之後的字元為: E
%var:~-2,5% 截取之後的字元為: EF
%var:~-2,9% 截取之後的字元為: EF
%var:~-2,13% 截取之後的字元為: EF
%var:~-5,1% 截取之後的字元為: B
%var:~-5,5% 截取之後的字元為: BCDEF
%var:~-5,9% 截取之後的字元為: BCDEF
%var:~-5,13% 截取之後的字元為: BCDEF
%var:~-8,1% 截取之後的字元為: 8
%var:~-8,5% 截取之後的字元為: 89ABC
%var:~-8,9% 截取之後的字元為: 89ABCDEF
%var:~-8,13% 截取之後的字元為: 89ABCDEF
%var:~-11,1% 截取之後的字元為: 5
%var:~-11,5% 截取之後的字元為: 56789
%var:~-11,9% 截取之後的字元為: 56789ABCD
%var:~-11,13% 截取之後的字元為: 56789ABCDEF
%var:~-14,1% 截取之後的字元為: 2
%var:~-14,5% 截取之後的字元為: 23456
%var:~-14,9% 截取之後的字元為: 23456789A
%var:~-14,13% 截取之後的字元為: 23456789ABCDE

%var:~-1,-2% 截取之後的字元為:
%var:~-1,-5% 截取之後的字元為:
%var:~-1,-8% 截取之後的字元為:
%var:~-1,-11% 截取之後的字元為:
%var:~-1,-14% 截取之後的字元為:
%var:~-5,-2% 截取之後的字元為: BCD
%var:~-5,-5% 截取之後的字元為:
%var:~-5,-8% 截取之後的字元為:
%var:~-5,-11% 截取之後的字元為:
%var:~-5,-14% 截取之後的字元為:
%var:~-9,-2% 截取之後的字元為: 789ABCD
%var:~-9,-5% 截取之後的字元為: 789A
%var:~-9,-8% 截取之後的字元為: 7
%var:~-9,-11% 截取之後的字元為:
%var:~-9,-14% 截取之後的字元為:
%var:~-13,-2% 截取之後的字元為: 3456789ABCD
%var:~-13,-5% 截取之後的字元為: 3456789A
%var:~-13,-8% 截取之後的字元為: 34567
%var:~-13,-11% 截取之後的字元為: 34
%var:~-13,-14% 截取之後的字元為:

有的變數截取之後值為空,這是正常的

如何用FTP自動傳送文件

FTP命令我就不多說,上網查或自行在命令列模式,先輸入ftp再輸入help即可得知

1.先建立一個文字檔,存成ftpcmd.txt,內容如下,請自行替換
open 11.10.2.xxx
帳號

密碼

binary
put D:\dbbk.zip
bye

有沒有注意到我的帳號跟密碼下一行都是空白,有的情況可以不用空,有的情況要,請自行測試囉

2.在命令列模式下,輸入
ftp -s:d:\ftpcmd.txt

此例ftpcmd.txt在D槽

3.配合排程,就可以自動傳送囉

順便再介紹一個在ftp裡面可以使用其他DOS命令的方法,用"!"囉
! Escape to the shell

下面的例子,把c槽dirtmp.log移動到d槽囉
!move c:\dirtmp.log d:\

這樣了吧

資料完整性設定(PRIMARY KEY與 FOREIGN KEY)

這是書上的例子,忘記是哪本了,參考看看,把以下的陳述式copy過去,一段一段執行,應該會對資料完整性的設定有初步的認識喔

/*
SQL 2000 只有NO ACTION CASCADE
SQL 2005 有NO ACTION CASCADE SET NULL SET DEFAULT
本文不介紹SET DEFAULT,個人覺得不實用囉
*/

--刪除資料表
drop table Scores
drop table Students
--
create table Students
( stuID int NOT NULL primary key, --學生代號
stuName nvarchar(20) NOT NULL, --學生姓名
SID varchar(50) not null unique, --保險號碼
birthdate datetime check (birthdate < getdate()), --生日
Address nvarchar(50) null, --地址
stuLeader int references Students(stuID) --組長代號
)
GO
/*NO ACTION,建立外部索引鍵時沒有特別宣告的話,就是使用此選項囉,如同一般的外部
 索引鍵的建立,被參閱資料刪除或是修改都會引發錯誤訊息的*/
create table Scores
( stuID int not null
foreign key references Students(stuID), --學生代號
Period varchar(30) not null, --學期
stuScore numeric(5,2) default 0, --成績
keyInUSR nvarchar(50) default suser_sname() --建檔人員
primary key (stuID,Period)
)
GO

--新增三筆學生資料
insert into Students values(1, N'lewis', '009988', '1997/7/1', 'Taipei', null)
insert into Students values(2, N'ada', '006688', '1998/5/1', 'Taipei', null)
insert into Students values(3, N'julla', '005588', '1995/7/1', 'Taipei', null)
go
--新增兩筆學生成績資料
insert into Scores values(1, '200601', 90, default)
insert into Scores values(2, '200601', 80, default)
go
--刪除學生資料
delete from Students where stuID = 1
--結果
/*訊息 547,層級 16,狀態 0,行 1
DELETE 陳述式與 REFERENCE 條件約束 "FK__Scores__stuID__0425A276" 衝突。衝突發生在資料庫 "myDB",資料表 "dbo.Scores", column 'stuID'。
陳述式已經結束。*/

/******************************************/

drop table Scores
truncate table Students
/*ON UPDATEDELETE CASCADE,宣告被參閱資料刪除或是修改時,一併
修改參閱的資料喔。如果學生更換代號時,系統會一併更換成績資料表的學
生代號。學生資料刪除時,成績資料一併刪除。很方便,我都不知道有這功能*/
--在Scores資料表中宣告ON UPDATE CASCADE ON DELETE CASCADE
create table scores
( stuID int not null
foreign key references Students(stuID)
ON UPDATE CASCADE ON DELETE CASCADE, --學生代號
Period varchar(30) not null, --學期
stuScore numeric(5,2) default 0, --成績
keyInUSR nvarchar(50) default suser_sname() --建檔人員
primary key (stuID,Period)
)
--新增三筆學生資料
insert into Students values(1, N'lewis', '009988', '1997/7/1', 'Taipei', null)
insert into Students values(2, N'ada', '006688', '1998/5/1', 'Taipei', null)
insert into Students values(3, N'julla', '005588', '1995/7/1', 'Taipei', null)
go
--新增兩筆學生成績資料
insert into Scores values(1, '200601', 90, default)
insert into Scores values(2, '200601', 80, default)
go
--查詢一下資料
select * from Students
--1 lewis 009988 1997-07-01 00:00:00.000 Taipei NULL
--2 ada 006688 1998-05-01 00:00:00.000 Taipei NULL
--3 julla 005588 1995-07-01 00:00:00.000 Taipei NULL
select * from Scores
--1 200601 90.00 shaq
--2 200601 80.00 shaq

--刪除1號學生
delete from Students where stuID = 1
--結果
/*(1 個資料列受到影響)*/
--竟然沒有錯誤耶,再查詢一下資料,發現雖然你只刪除Students資料表的資料,
--居然Scores資料表的資料也一併刪除了...神奇啊
select * from Students
--2 ada 006688 1998-05-01 00:00:00.000 Taipei NULL
--3 julla 005588 1995-07-01 00:00:00.000 Taipei NULL
select * from Scores
--2 200601 80.00 shaq

--更改2號學生編號
update Students set stuID = 200 where stuID = 2
--結果
--(1 個資料列受到影響)
--再查詢一下Scores資料表,發現Scores資料也跟著異動了喔
select * from Students
--3 julla 005588 1995-07-01 00:00:00.000 Taipei NULL
--200 ada 006688 1998-05-01 00:00:00.000 Taipei NULL
select * from Scores
--200 200601 80.00 shaq

/******************************************/

drop table Scores
truncate table Students
/*ON UPDATEDELETE SET NULL,就是被參閱資料刪除或是修改時,參
閱的資料就更改成null值了。例如有學生被刪除或是更換學號時,原成績
的學生代號,統一更改為null。取代刪除或隨之更改的動作*/
--在Scores資料表中宣告ON UPDATE SET NULL ON DELETE SET NULL
create table scores
( stuID int
foreign key references Students(stuID)
ON UPDATE SET NULL ON DELETE SET NULL, --學生代號
Period varchar(30) not null, --學期
stuScore numeric(5,2) default 0, --成績
keyInUSR nvarchar(50) default suser_sname() --建檔人員
)
--新增三筆學生資料
insert into Students values(1, N'lewis', '009988', '1997/7/1', 'Taipei', null)
insert into Students values(2, N'ada', '006688', '1998/5/1', 'Taipei', null)
insert into Students values(3, N'julla', '005588', '1995/7/1', 'Taipei', null)
go
--新增兩筆學生成績資料
insert into Scores values(1, '200601', 90, default)
insert into Scores values(2, '200601', 80, default)
go
--查詢一下資料
select * from Students
--1 lewis 009988 1997-07-01 00:00:00.000 Taipei NULL
--2 ada 006688 1998-05-01 00:00:00.000 Taipei NULL
--3 julla 005588 1995-07-01 00:00:00.000 Taipei NULL
select * from Scores
--1 200601 90.00 shaq
--2 200601 80.00 shaq

--刪除1號學生
delete from Students where stuID = 1
--結果
/*(1 個資料列受到影響)*/
--查詢一下資料,發現Scores原stuID為1的值已變為NULL囉
select * from Students
--2 ada 006688 1998-05-01 00:00:00.000 Taipei NULL
--3 julla 005588 1995-07-01 00:00:00.000 Taipei NULL
select * from Scores
--NULL 200601 90.00 shaq
--2 200601 80.00 shaq

--更改2號學生資料
update Students set stuID = 200 where stuID = 2
--結果
/*(1 個資料列受到影響)*/
--查詢一下資料,發現Students的stuID變為200,Scores原stuID值都變為NULL囉
select * from Students
--3 julla 005588 1995-07-01 00:00:00.000 Taipei NULL
--200 ada 006688 1998-05-01 00:00:00.000 Taipei NULL
select * from Scores
--NULL 200601 90.00 shaq
--NULL 200601 80.00 shaq