顯示具有 MS SQL 標籤的文章。 顯示所有文章
顯示具有 MS SQL 標籤的文章。 顯示所有文章

2015年8月13日 星期四

Visual Studio 2015 的localDB

好久沒更新部落格…近半年已無時間跟體力在文章上,但依然遇到一些問題還是有做一些未經整理的筆記,有時間再一一補上來分享….

今年依然是個技術大爆發的一年,前陣子將開發環境重新安裝成 Win 10 + Visual Studio 2015後,原本在2013 Run的專案,SQL Server是用本機的localDB,但用VS 2015開已經連不上,至於什麼是localDB呢?可以看看保哥這篇文章:

再以往使用localdb你的連線字串可能看起來會是這樣:

<add name="ConnectionString" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=DataBaseName;Persist Security Info=True;MultipleActiveResultSets=True;Application Name=EntityFramework" providerName="System.Data.SqlClient" />


再VS 2015 開始有了新的命名方式,必須改用 (localdb)\MSSQLLocalDB 來取代

<add name="ConnectionString" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DataBaseName;Persist Security Info=True;MultipleActiveResultSets=True;Application Name=EntityFramework" providerName="System.Data.SqlClient" />


當然,如果還是要用舊的執行個體,也可以下載安裝:


https://msdn.microsoft.com/zh-tw/sqlserver2014express.aspx


--


一點小筆記...

2014年1月16日 星期四

T-SQL如何join到函數(function)回傳的Table資料

回答論壇問題順便做個紀錄,「SQL字串找尋問題

如何將下列資料用select語法取出B開頭的資料呢?

ID Data
001 A000,B000,C000
002 B000,D000,E000

希望結果:

001 B000

002 B000

最主要先切割字串來分析,首先搭配之前寫的備忘錄,通常我會在SQL建立一個切割字串的函數「在T-SQL裡面切割字串(Spilt String)

接著就能將這個函數回傳的table join起來,再進行篩選

Declare @table Table
(
ID VARCHAR(3),
data NVARCHAR(15)
)

Insert INTO @table values ('001','A000,B000,C000')
Insert INTO @table values ('002','B000,D000,E000')


select tb.id,tb2.data from @table tb
CROSS APPLY Split(data,',') AS tb2
where tb2.data like 'B%'

特別APPLY是SQL 2005之後才提供的語法,所以要注意版本相容性


APPLY又分為CROSS APPLY和OUTER APPLY,


CROSS APPLY 可以把發成我們常用的inner join ,會查詢有交集的結果


OUTER APPLY就相當於left join,會以左邊的資料表為主


詳細的範例可以以上面的MSDN連結延伸閱讀。


執行結果:


image

2014年1月15日 星期三

在T-SQL裡面切割字串(Spilt String)

這是一篇小備忘錄,在DB我通常會用一些自訂函數來解決一些事情,例如分割字串,在程式裡都有內建函式可以用,但SQL就沒有,所以建一個起來再寫T-SQL時會蠻方便的

image

Code :

USE [lenton]
GO
/****** Object: UserDefinedFunction [dbo].[Split] Script Date: 2014/1/16 下午 02:42:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Split]
(
@RowData varchar(8000),
@SplitOn nvarchar(1)
)
RETURNS @RtnValue table
(
Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare @Cnt int
Set @Cnt = 1

While (Charindex(@SplitOn,@RowData)>0)
Begin
Insert Into @RtnValue (data)
Select
Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))

Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
Set @Cnt = @Cnt + 1
End

Insert Into @RtnValue (data)
Select Data = ltrim(rtrim(@RowData))

Return
END



2014年1月12日 星期日

在SQL Server 2012 or LocalDB 附加安裝北風資料庫

微軟在以往SQL 2000時代就有提供北風資料庫(Northwind)供下載測試,安裝方式就不再多說,Google一下就有很多教學,例如此篇文章,而在SQL 2012後安裝後會發現無法附加,微軟又提供另一個範例資料庫叫Adventure Works 範例資料庫,雖然這個資料庫關聯很多,資料表命名也更整齊,但通常會用到範例資料庫應該都只是撰寫些Demo,不希望有太複雜關聯的資料庫吧,故本文章主要教學如何在SQL Server 2012安裝北風資料庫,以LocalDB為例。

以傳統附加方式會發生以下錯誤:

image

 

這主要是因為一些相容性問題導致附加失敗,而我們可以用另外一種方式來建立,首先先到從此下載的北風資料庫安裝檔,而預設安裝資料夾為C:\SQL Server 2000 Sample Databases,打開後會有以下檔案,打開instnwnd檔案

 

image

將以下兩行程式碼註解並執行

exec sp_dboption 'Northwind','trunc. log on chkpt.','true'

exec sp_dboption 'Northwind','select into/bulkcopy','true'

 

image

 

這樣就會發現建立完成了 : )

 

image


參考資料

http://buli.waw.pl/sql-server-2012-northwind-database/

2013年12月7日 星期六

[ASP.NET]相同的IIS,讓多個網站共用Session資訊

前言

先談談為什麼會有此需求吧,擔任甲方的IT部門最大的挑戰就是要維護舊的系統,要瞭解很多的business logic,而因為舊系統技術過舊架構也不太好,造成維護困難,故提出了重構的建議,但現實往往不可能那麼美好,因為還是要面對新的需求,處理使用者的操作問題,又因人力不足沒辦法專注的在重構這件事,所以只能列出計畫,有計劃性的慢慢重構,而短期目標就是舊的系統不要在增肥,而新的需求遵循新的架構走。

本公司舊系統是WebForm 2.0的Website,我試著導入MVC,故最初的想法是將舊網站先升級到FrameWork 4.0,再將新的MVC Application加入進去,但升級上遇到了困難,因舊的WebSite有買第三方Grid套件,故他是綁死在.NET 2.0的,嘗試升級後整個就悲劇了,故開始朝向兩個Website去處理,而遇到的課題就是一些Session資料如何共用:

1.將使用者的資訊存入Cookie - 可行,但有安全性的疑慮

2.利用SQL Server的Session機制實現

本篇將介紹第二點的實現方式

Step 1 建置並發佈兩個網站

image

而在這網站新增一個WebForm,程式也簡單到不行,秀出當前的Session及新增Session功能

image

Step 2 建置存放Session專用的資料庫

進入C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319 將此路徑複製

image

進入命令提示字元,鍵入以下指令

aspnet_regsql.exe -S 資料庫主機IP -U sa -P 密碼 -ssadd -sstype c -d 資料庫名稱

請依情況去改變上方參數

image

利用SSMS,就可看到資料庫已經建置完成

image

Step 3 修改WebSite的Web.config

在Web.config system.web區塊加入以下程式,程式區塊都不用動

<sessionState mode="SQLServer" sqlConnectionString="data source=KYLE;initial catalog=SessionPool;user id=sa;password=kyle" allowCustomSqlDatabase="true"  timeout="120"/>

Step 4 修改SQL Session Table

進入DB,會看到有以下兩個表: 

ASPStateTempApplications 用來儲存應用程式的ID和名稱

ASPStateTempSessions 用來儲存Session的值

image

先兩分別Run看看在兩個網站寫入一個Session資料會變什麼情況

image

會發現會有兩筆AppName,而ASPStateTempSessions 則會有Session紀錄

接著最重要的,其實就是在SQL stored procedure做些手腳,讓不同的Apps,指向同一個AppName

打開預存程序dbo.TempGetAppID

image

修改@appName

image

這樣就大功告成了,我們重啟IIS和SQL,把Session清掉再來各新增一筆看看:

image

後記

建議,要重構還是整個重新規劃會比較好,畢竟Session移到SQL上,DB因為connection次數變多而負擔加重,多少會有些效能問題,但不能忍受古人的技術債又因為一些因素影響的人,就可以參考這種方式 T___T

--

Reference

http://www.cnblogs.com/haoxue/archive/2010/10/11/asp_net_session_share.html

http://www.debugease.com/aspdotnet/1712975.html

[MS SQL]如何抓取某筆資料的上下筆(Cross Join)

朋友問到,如何將下圖的資料,抓取指定的上下筆,以新聞輪播的功能來舉例:

image

用程式來講蠻單純的,只要取得目前的ID,就可以用select top 1 + where條件就可以完成,

但這樣有可能要connection兩次,所以就寫了一個Script + CROSS JOIN 來解決 :P

Script

declare @TABLE TABLE (ID int,Title nvarchar(50))
declare @tagetID int

--新增資料
INSERT INTO @TABLE VALUES(1,N'新聞標題1')
INSERT INTO @TABLE VALUES(2,N'新聞標題2')
INSERT INTO @TABLE VALUES(3,N'新聞標題3')
INSERT INTO @TABLE VALUES(4,N'新聞標題4')
INSERT INTO @TABLE VALUES(5,N'新聞標題5')

select * from @TABLE

set @tagetID = 3 --抓取ID為3的上下筆

SELECT P.PrevID,P.Name as 'Prev News', N.NextID,N.Name as 'Next News' FROM
(
SELECT MAX(A.id) PrevID,
(select Title FROM @TABLE where id = MAX(A.id)) Name
from @TABLE A
where A.id < @tagetID
) P
CROSS JOIN
(
SELECT MIN(A.id) NextID,
(select Title FROM @TABLE where id = MAX(A.id)) Name
from @TABLE A
where A.id > @tagetID
) N


CROSS JOIN


Cross Join 是一個實現笛卡兒乘積 (Cartesian Product)的語法,已兩個table來講,如tableA資料5筆,table資料4筆,select出來就會是20筆,用文字說明有點複雜,以下寫個Sample :

declare @employee TABLE (empID int,Name nvarchar(50)) --員工表
declare @Dept TABLE (DeptID int,Name nvarchar(50)) --部門表

--新增資料
INSERT INTO @employee VALUES(1,N'周杰倫')
INSERT INTO @employee VALUES(2,N'蕭敬騰')
INSERT INTO @employee VALUES(3,N'方大同')

INSERT INTO @Dept VALUES(1,N'財務部')
INSERT INTO @Dept VALUES(2,N'行銷部')
INSERT INTO @Dept VALUES(3,N'研發部')


select * from @employee cross join @Dept -- 3 * 3 9筆資料

--結果等同於
select * from @employee,@Dept

image


使用如果不慎注意會是效能殺手,譬如1000*1000筆資料吃的效能可是很可怕的,而回到上例,其實上一頁跟下一頁都只是會有一筆資料而已,故只是很簡單的應用讓他查詢出來會是一筆記錄


--


Reference


http://technet.microsoft.com/zh-tw/library/ms190690(v=sql.105).aspx


http://blog.csdn.net/xiaolinyouni/article/details/6943337

[MS SQL]寫給新手的Cursor小筆記

前言

雖然網路範例非常多,但之前在回答新手問題時,丟了一些範例連結給他,他還是看不太懂,後來就自己寫了一個範例加註釋,終於讓他瞭解並應用,所以我想試著用自己的解釋方式紀錄下來,提供給一些還不熟悉的初心者。

Cursor(資料指標)

常常我們都會在程式撰寫迴圈,在SQL裡面就是使用Cusor,Cursor會先從資料庫裡面讀出資料,暫存於tempDB資料庫內,再從tempDB逐筆讀出處理,就因為有寫入tempDB的動作,所以使用上也要注意,譬如我看過明明就能用update語法直接處理掉的程式,還使用Cusor逐筆跑出去update,這種影響效能就會非常巨大。

一個簡單的Cursor範例


--定義Cursor並打開
DECLARE MyCursor Cursor FOR --宣告,名稱為MyCursor

-- 此區段就可以撰寫你的資料集,如找出名稱為John的資料
select id from tableA where name like '%John%'

Open MyCursor


print @@CURSOR_rows --查看總筆數


--定義ID變數
declare @id varchar(25) --用來存放ID的變數

--開始迴圈跑Cursor Start
Fetch NEXT FROM MyCursor INTO @id
While (@@FETCH_STATUS <> -1)
BEGIN

--此區塊就可以處理商業邏輯,譬如利用tableA的ID將資料塞入tableB
insert into tableB
select top 1 * from tableA where id=@id

Fetch NEXT FROM MyCursor INTO @id
END

--開始迴圈跑Cursor End

--關閉&釋放cursor
CLOSE MyCursor
DEALLOCATE MyCursor


--


Reference


http://sharedderrick.blogspot.tw/2013/02/cursors-rowsets.html

2013年11月29日 星期五

[MS-SQL]SQL自訂函數回傳Table

以往寫T-SQL函數通常都Return一個值,但今天學到也可以回傳Table的資料,底下寫一個範例,針對傳入不同的條件,回傳不同的Table:

CREATE FUNCTION [dbo].[Test_Function]
(@ID int)
RETURNS @TABLE TABLE (
ID varchar(25),
Number varchar(25)
)
AS
BEGIN

IF @ID = 1
begin
INSERT INTO @TABLE (ID,Number)
select 'ID1','ID Number 1'
end
else
BEGIN
INSERT INTO @TABLE (ID,Number)
select 'ID2','ID Number 2'
end

RETURN
END

如果Table欄位太多,定義上麻煩可以參考我之前寫的文章,


使用TempTable的方式: http://kyleshen616.blogspot.tw/2013/10/ms-sqltemp-tableifelse-if_29.html

2013年10月29日 星期二

[MS SQL]使用#Temp Table在if…else if 條件分支使用小筆記

前言


因為工作的關係,這幾個月來開始大量接觸複雜T-SQL,所以遇到有些問題都會筆記下來,順便做個分享(真懷念程式與DB權責分離的時候 T___T)

 

Temporary Tables


在SQL Server裡,創建方式又分為Create及Declare,前者儲存於DB的TempDB中,後者儲存於記憶體裡,當Session關閉連線時,暫存Table將會Drop掉。
暫存表的使用方式可以參考以下文章:

MS SQL 建立暫存表格 temp table
建立#TempTable與Declare @TempTable有何差別

 

條件分支遇到的問題


今天撰寫Temp Table遇到了if…else if遇到了執行錯誤的問題,我試著用簡單的邏輯來記錄下來。
這是一個很簡單的if…else if判斷,但在不同的分支下加入暫存表的寫法就會發生2714的錯誤

image

在into之前drop掉也無法:

image

後來找到微軟有官方的解答(機器翻譯),照他給的Sample Code進行些修改,將定義Table的抽出外層,不同的是,他的Temp欄位只有一個,而我的欄位有非常多所以不可能一個一個宣告,所以我先Select top 0 將欄位INTO到Temp Table,接著再依不同條件Inserty資料,改寫完的Code如下:
-- 如果Temp Table存在,則清除
IF object_id(N'tempdb.dbo.#TempTable') IS NOT NULL drop table TempTable

select TOP 0 * INTO #TempTable from DemoTable

if (1=1) 
    begin
        INSERT INTO #TempTable 
        select * from DemoTable where ColumnName = 'Filter1'
    end
else if (1=2)
    begin
        INSERT INTO #TempTable
        select *  from DemoTable where ColumnName = 'Filter2'
    end

SELECT * FROM #TempTable

--Do something ....

--

Reference

http://stackoverflow.com/questions/4155996/sql-insert-into-temp-table-in-both-if-and-else-blocks

http://social.msdn.microsoft.com/forums/sqlserver/en-US/42a377a6-8d2f-4666-bf86-f0d005cde51c/tsql-same-temp-table-in-if-else-block-error

http://deanma.blogspot.tw/2012/01/ms-sql-temp-table.html

2013年9月27日 星期五

[ASP.NET]GridView小計欄跟總計欄的解決方案-使用SQL語法

ASP.NET的GridView是我覺得最方便的Server控制項,在公司內部有很多的報表,主要邏輯都寫在SQL裡面,而在GridView裡就能變得比較單純去繫結資料,並修改一些顯示樣式即可,而小計欄和總計欄又是報表常常會遇到的欄位,本篇文章將Step by Step來實做如何建置這樣的報表。
1.新增一個WebForm,並拉一個GridView控制項至畫面
1
2.移至設計畫面,選擇GridView屬性,修改ID以便程式好閱讀
2 3
3.再來看一下本範例的資料表設計,基本上不會太複雜,分為員工編號、部門、年薪三個欄位
4
4.撰寫SQL語句,也是本文的重點,使用SQL的Grouping語法
NoteGROUPING (Transact-SQL)指出是否彙總 GROUP BY 清單中指定的資料行運算式。 GROUPING 傳回 1 時,表示會在結果集中彙總,傳回 0 則不會。 當指定 GROUP BY 時,GROUPING 只能在 SELECT <select> 清單、HAVING 和 ORDER BY 子句中使用。From MSDN
使用方式如下:
select 
case when grouping(Dept)=1 then N'合計' else isnull(StaffNumber,'') end '員工編號',
case when grouping(StaffNumber)=1 and grouping(Dept)=0 then N'小計' else isnull(Dept,'') end '部門',
sum(pay) as '年薪'
from GirdTest group by Dept,StaffNumber with rollup

如此就能很方便的完成小計欄跟合計欄了:

5

5.接著回到.aspx.cs開始撰寫程式,於Page_Load的時候Binding資料,GetData()是處理資料的自定義function

6
private DataTable GetData()
{
    DataTable dt = new DataTable();
    string Sql = @"
                select 
                case when grouping(Dept)=1 then N'合計' else isnull(StaffNumber,'') end '員工編號',
                case when grouping(StaffNumber)=1 and grouping(Dept)=0 then N'小計' else isnull(Dept,'') end '部門',
                sum(pay) as '年薪'
                from GirdTest group by Dept,StaffNumber with rollup";

    using (SqlConnection connection =
    new SqlConnection(connectionString))
    {
        SqlCommand command = new SqlCommand(Sql, connection);
        try
        {
            connection.Open();
            SqlDataReader reader = command.ExecuteReader();
            dt.Load(reader);
            reader.Close();
            return dt;
        }
        catch (Exception ex)
        {
            //Error logging...
        }
    }
    return dt;
}

6.回到設計頁面,選擇編輯資料行

7


7.加入三個BoundField,並修改HeaderText

8

8.修改DataField,這裡對應的為SQL Select出來的欄位

image

9.接著因為預設的GridView都為白色,我們選擇自動格式化來調整一下版型

image

10.Done!!

image

結論

很多人的做法也會選擇在GirdView的RowDataBind事件做欄位的處理,可參考這篇文章,此篇文章比較囉嗦一點,實際上開發GridView報表其實是很快的一件事,因為希望能幫助到正在學習ASP.NET的初心者,筆者好像幾年前真的遇到卡這個問題卡到快瘋掉的同事XD,當然除了GridView外,還有很多的選擇,如Reporting Service、Crystal Report…等等,可依照自己喜好及好維護的方式去完成囉。

2013年5月31日 星期五

[MS SQL]Could not allocate space for object 'XXX'.'YYY' in database 'distribution' because the 'PRIMARY' filegroup is full

之前遇到幾個DB問題,環境大概是多台DB做點對點交易式複寫 (Peer-to-Peer Transactional Replication),至於這是怎麼運作的可以參考這幾篇文章:

http://caryhsu.blogspot.tw/2012/03/sql-server-nlb.html

http://www.dotblogs.com.tw/jerrymow/archive/2010/12/29/20447.aspx

原本都Run的好好的,今天早上一上班信箱就開始被failed mail塞爆,這對以往沒有管過DB的我,腎上腺素直直上升阿(一定是沒買乖乖的關係…),所以一定要來記錄一下。

首先去Log查看,發現有以下錯誤:

Could not allocate space for object 'XXX'.'YYY' in database 'distribution' because the 'PRIMARY' filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, addingadditional files to the filegroup, or setting autogrowth on for existing files in the filegroup.

嗯…錯誤訊息很明顯…大概就是資料滿了,所以找了好久,最後至下方調整:

在'distribution' 點選右鍵->Properties

 

image

選擇Files tab->點選initial size下的按鈕

image

調整Maximum File Size至Unrestricted File Growth,再去跑JOB就正常執行了(呼)!

image

--

Reference

http://support.powerdnn.com/KB/a132/error-could-not-allocate-space-object-x-dabase-your.aspx

2013年5月24日 星期五

[MS SQL]含有上午or下午字串轉成DateTime之錯誤處理

前言

此篇文章標題實在很難下,所以我需要描述一下情境。因最近接手一個國外的Project,首先必須先將開發環境建置起來,但有關日期的程式寫法,都是在C#將Datetime直接ToString,然後這個string直接丟到SP去處理,正式環境都跑得好好的,測試環境在DB就發生了日期轉型錯誤的Exception。

還原&除錯

在C#裡,會產生出類似這種string,Response的結果會是2013/5/25 上午 00:21:25這種格式

image

之後這個string,會丟到SP做一些處理,這種格式就會發生錯誤

image

當然可以修改程式,讓ToString時可以自己指定格式,如下圖

image

但整個工程太浩大,暫時不想花那麼多時間去重構程式,因DataTime的時間,是抓該台Server的日期設定格式,故朝著修改Server設定的想法去做,讓測試環境能Run起來,而到時因正式環境會全是英文,故比較不會出現有中文字串之問題。

首先先到控制台>時間語言語和區域>地區及語言

image

調整日期格式,將tt hh:mm調整為HH:mm: ss(24小時制)

QQ截圖20130523143252 QQ截圖20130523143309

照理修改完後,去頁面執行應該會是輸出此格式,但發現還是沒變(重開機也一樣)

真的很詭異,後來發現登錄檔的值根本沒變,故直接朝著他下手…在執行視窗輸入執行regedit.exe

image

進入底下路徑,將sShortTime及sTimeFormat的tt格式拿掉,之後再重開機

image

如此在頁面上,Response出來就會是2013/5/25 00:33:29這種格式,丟進SP也不會出錯了

image

後記

其實看不同國家的Code還蠻有趣的,會考慮到語系、編碼之類的問題,在看這些Code也覺得這些小地方可能要再多考慮一點,如Datetime還是把他格式標準化比較好。

2013年4月24日 星期三

[Azure]Invalid object name 'sys.configurations'. (Microsoft SQL Server, 錯誤: 208)

最近比較有時間來玩玩Azure,微軟超彿心的有90天的免費申請,對於學生或還在評估的企業真的很方便

Azure有提供類似SSMS的Silverlight介面提供開發人員去寫入SQL command

但還是習慣用SSMS(Sql Management Studio)來撰寫SQL,故此篇主要紀錄用SSMS連到Azure SQL DataBase時發生的問題

操作步驟如下:

點選ADO.NET的檢視連線字串

image

 

這邊會秀出用來連線的語法

image

將上敘的Server、User ID、Password打入SSMS連線,會發生第一個錯誤

image

原因為IP未加入防火牆,我們回到Azure的管理介面,將目前的IP加入

3

接著再連線看看…接著發現一個奇怪的錯誤,錯誤代碼為208

 

image

試了好多連線方式都無法連,只好拜請Google大師了,後來才在國外論壇發現可能是版本問題QQ

小弟的版本為 SQL Server 2008,而Azure需要的版本好像是R2之後,故至官網下載後就可以連了!

4 image

 

後記

小弟對於Azure是超級菜新手,如文章內容有錯煩請告知,會馬上做處理,以免誤人子弟Q_Q

參考資料

http://social.msdn.microsoft.com/Forums/en-US/windowsazuredata/thread/eb7a840f-6c2c-4ebe-b86a-a18374e685c1