Sql Server數據庫小知識點總結


 

  把我在開發時候遇到的一點小知識持續更新在這里~

 

1.where條件時常變

where UserID='1' 這里的UserID呢,它的值是經常在變化的,有時候要查2,有時候要查3的,有時候要查全部人!這里定義一個函數傳參數的時候,查全部人這里需要搞一個if分支判斷一下,但是呢,不需要~~好的辦法來了

select * from 表 Where UserID="+UserID+" 

大概就是這樣子,UserID是一個參數,你有需要的時候直接傳給我1或者2或者其他數字都OK,但是你不需要這個條件的時候,只需要傳給我UserID這個就行了,UserID=UserID會查出所有的數據~

 

2.聯表查詢都知道,現在來試試三表查詢

 

 Sql = "select * from VehicleRegistration a inner join TB_DictData b on a.VehicleID=b.Name inner join T_ACL_User c on a.UserID=c.ID  where b.Value='" + Value + "'";

多個inner join on 就ok了

 

3.出現這樣的錯誤:

消息 8120,級別 16,狀態 1,第 6 行
選擇列表中的列 'a.Value' 無效,因為該列沒有包含在聚合函數或 GROUP BY 子句中。

原因以及解決辦法:

凡是在group by后面出現的字段,必須同時在select后面出現;凡是在select后面出現的、同時未在聚合函數中出現的字段,必須同時出現在group by后面”,檢查sql是否符合上述法則。

其實這個group by還有一些需要注意的地方,在select后面的如果是 as 某一列存在的話是不需要出現在group by后面的,還有,如果select后面出現聚合函數,例如SUM,count等,則一定要有group by存在 

 

4.書寫sql語句的方法(一個資深的同事建議,寫在using語句里面可以自動釋放數據庫鏈接)

  public static DataTable SqlConnectionInformation()
        {
            string connstr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;    
            DataTable dt = new DataTable();
            using (SqlConnection conn = new SqlConnection(connstr))
            {
                if (conn.State == ConnectionState.Closed)
                {
                    conn.Open();   
                } 
                string sql = "select * from table";
                SqlCommand com = new SqlCommand(sql, conn);
                SqlDataAdapter adapter = new SqlDataAdapter(com);
                adapter.Fill(dt);  
            }

            return dt; 
        
        }

 

 5.要學會使用in啊,我腦殘的寫了一大串子...

select * from WEB_ItemInfo i where id in(26933,26934,26935,26936,26937,26938,26939,26940,26941)

我傻逼的寫了9次,然后用union連接了起來

6.學會使用CTE公用表表達式

with t as
(
 select * from ......
)
select * from t where .....

  這是簡單的CTE,可以寫復雜一點,比如想對表的查詢結果繼續進行操作,那么就多寫幾個CTE

with t as(
select CONVERT(varchar(8), a.ItemDate, 112) as datekey ,left(i.Name,5)as Name,a.ItemValue
from Web_ItemInfo i inner join AnalysisData a  on i.ID in(26933,26934,26935,26936,26937,26938,26939,26940,26941) and i.ID=a.ItemID
),
t1 as(
select  convert(varchar(20),'蜀雲泉真帥啊') as plantname ,convert(varchar(20),'音樂家')  as divisionname,t.datekey,t.Name,SUM(ItemValue) as data from t where datekey>= dbo.GetUpdateDateKey()
group by Name,datekey
),
t2 as(
select convert(varchar(20),'蜀雲泉真帥啊') as plantname,convert(varchar(20),'音樂家')  as divisionname,
convert(varchar(12),replace(date_day,'-','')) as datekey,b.pumpname,
(isnull(h0,0)+isnull(h1,0)+isnull(h2,0)+isnull(h3,0)+isnull(h4,0)+isnull(h5,0)
+isnull(h6,0)+isnull(h7,0)+isnull(h8,0)+isnull(h9,0)
+isnull(h10,0)+isnull(h11,0)+isnull(h12,0)+isnull(h13,0)+isnull(h14,0)
+isnull(h15,0)+isnull(h16,0)+isnull(h17,0)+isnull(h18,0)+isnull(h19,0)
+isnull(h20,0)+isnull(h21,0)+isnull(h22,0)+isnull(h23,0))/60 as data
from web_daydata a inner join web_pumpconfig b on b.scid=a.id
where date_day>=dbo.GetUpdateDate()
),
t3 as(
    select * from t1 union all select * from t2 
)
select e.Equipmentid,11 as PlantID,18 asDivisionID,t3.* from t3 inner join SZWG.dbo.Dim_Equipment e on 11=e.PlantID and 18=e.DivisionID and Name=e.EquipmentName

 

7.連表查詢還可以這樣來,不需要寫那么多的inner join 

select * from table1 1,table2 2 .....

8.pivot和unpivot行轉列和列轉行

with t as(
SELECT P.Date_Month,P.Supplier,P.data
FROM 
(
   select Date_Month,sum(d1) as d1, sum(d2) as d2,sum(d3) as d3,sum(d4) as d4,sum(d5) as d5,sum(d6) as d6,sum(d7) as d7,sum(d8) as d8,sum(d9) as d9,sum(d10) as d10,sum(d11) as d11,sum(d12) as d12,sum(d13) as d13,sum(d14) as d14,sum(d15) as d15,sum(d16) as d16,sum(d17) as d17,sum(d18) as d18,sum(d19) as d19,sum(d20) as d20,
sum(d21) as d21,sum(d22) as d22,sum(d23) as d23,sum(d24) as d24,sum(d25) as d25,sum(d26) as d26,sum(d27) as d27,sum(d28) as d28,sum(d29) as d29,sum(d30) as d30,sum(d31) as d31 from Web_MonthData_FuTianWasteWaterTreatmentPlant  where ID in (40204,40218)  group by Date_Month

)T
UNPIVOT 
(
    data FOR Supplier IN
    (d1, d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,d18,d19,d20,
    d21,d22,d23,d24,d25,d26,d27,d28,d29,d30,d31 )
) P
)
select replace(Date_Month+RIGHT(replace(supplier,'d','0'),2),'-','') as datekey,'福田水質凈化廠' as plantname, 
'一期' as divisionname,data as ItemValue,'預處理區用電' as 電種類 from t

 9.篩選某列只要數字的(如果=1說明是數字類型,如果=0說明不是數字類型)

where dbo.isReallyNumeric(b.daydata)=1

 

10.SSIS抽數據的時候做增量,這個應該不屬於sql的知識范疇,暫且寫在這里吧

t1.ItemDate>=isnull((select ConfiguredValue from  dbo.[SSIS Configurations] where configurationfilter='updatedate'),'2008-01-01')

 

 11.sql表里的數據生成insert腳本

 

 

 12.取得一個表的所有列名,但是不包括XX (BENG_TB是表名)

select name from syscolumns where  id=object_id('BENG_TB') and name not in ('DATE','TIME')

  需要注意的是 ,object_id里面必須寫表名,你寫數據庫.dbo.表名都不行,所以這東西只能在該表存在的數據庫中使用了

 

 13.SQL行列轉換中的IN不能寫select語句怎么辦?動態SQL可以實現!

declare @sql nvarchar(4000)
select  @sql=isnull(@sql+',','')+quotename(Name) from syscolumns where  id=object_id('BENG_TB') and name not in ('DATE','TIME')
declare @sqlstr varchar(4000)
set @sqlstr='select a.*,b.NodeID,b.TagName,301 as FactoryID from
(
SELECT rtrim(convert(varchar,replace([Date],''/'',''-'')))+'' ''+ ltrim(convert(varchar,[Time])) [DateTime] ,P.SupplyNum,p.Supplier
FROM 
(
    SELECT top 1 *
     FROM [QY_DATA].[dbo].[BENG_TB]
)T
UNPIVOT 
(    
    SupplyNum FOR Supplier IN
    ('+@sql+')
) P) a inner join Realtime5.dbo.Web_Node b on a.Supplier=b.TagName
' 
exec(@sqlstr)

動態SQL,屌屌的~

 

 14.order by多個字段排序(因為他們是字符格式,所以我都轉換了一下格式)

order by CONVERT(datetime,DATE,120) desc,CONVERT(datetime,TIME,120) desc

 

 15.多表聯表更新

update 表1 set Name=a.TagDescription  from 表2 a where ID=a.NodeID

還可以這樣

update a set
a.h0=b.h0,a.h1=b.h1,a.h2=b.h2,a.h3=b.h3,a.h4=b.h4,a.h5=b.h5,a.h6=b.h6,a.h7=b.h7,
a.h8=b.h8,a.h9=b.h9,a.h10=b.h10,a.h11=b.h11,a.h12=b.h12,a.h13=b.h13,a.h14=b.h14,
a.h15=b.h15,a.h16=b.h16,a.h17=b.h17,a.h18=b.h18,a.h19=b.h19,a.h20=b.h20,a.h21=b.h21,
a.h22=b.h22,a.h23=b.h23 from [IPMLBZ].[PMIS5].[dbo].Web_daydata a inner join [PMIS5].[dbo].Web_daydata b
on a.id = b.ID and a.ID= 23459 and a.date_day= b.date_day and a.Date_Day= '2018-08-27' 

但是這里需要注意一點,a.ID=這里,貌似不能用in (1,2,3),不能使用in,只能用等於號。這個不清楚為什么。

 16.獲取當前日期並判斷是星期幾

select   
case   datepart(dw,getdate()) 
when   1   then   '星期天 ' 
when   2   then   '星期一 ' 
when   3   then   '星期二 ' 
when   4   then   '星期三 ' 
when   5   then   '星期四 ' 
when   6   then   '星期五 ' 
when   7   then   '星期六 ' 
end

但是上面這個方法很麻煩,這里有一個更簡單的方法來判斷輸入的日期是周幾

select datename(weekday,'2018-06-01')

 

17.數據庫有的時候,我新建的表打不出來?說不存在?

ctrl+shift+R  按這個鍵,就會刷新,就可以打出表名了,還不行的話你多按幾下....

 

18.偷師學藝,數據庫53錯誤

在與 SQL Server 建立連接時出現與網絡相關的或特定於實例的錯誤。未找到或無法訪問服務器。請驗證實例名稱是否正確並且 SQL Server 已配置為允許遠程連接。 (provider: 命名管道提供程序, error: 40 - 無法打開到 SQL Server 的連接)
可以按照下面的步驟來做,就好了
打開Sql server 管理配置器或者在命令行輸入:SQLServerManager10.msc



然后重啟一個sql server的服務,重新打開SQL Server Management Studio,在服務器名稱輸入:(local)或者127.0.0.1,即可登錄數據庫了。

 

 

 19.根據in()里面的數據進行排序,也就是固定排序

我查詢的時候in()了一些數字,但是查出來之后自動排序了。我不想排序,可以使用charindex()方法,如下:

select * from AnalysisData where ItemID in(
11002,114101,214011
)  
Order By charindex(','+RTRIM(cast(ItemID as varchar(10)))+ ',',',11002,114101,214011,')

這樣就可以按照in里面的數字進行排序了

 

20.接着19講,Order by這里我又理解了一下

Order by應該只能用在語句的最后,例如:

select '當前' h,charindex(','+RTRIM(cast(winame as varchar(100)))+ ',',',pH值,渾濁度,臭和味,氨氮,游離余氯,總余氯,細菌總數,總大腸菌群,鋁')
,* from [dbo].[WaterQuality] (@date1,@date2)
where winame in('pH值','渾濁度','臭和味','氨氮','游離余氯','總余氯','細菌總數','總大腸菌群','')

union 

select '同比' h,charindex(','+RTRIM(cast(winame as varchar(100)))+ ',',',pH值,渾濁度,臭和味,氨氮,游離余氯,總余氯,細菌總數,總大腸菌群,鋁')
,* from [dbo].[WaterQuality] (Convert(varchar(10),(Dateadd(YEAR,-1,@date1)),23),Convert(varchar(10),(Dateadd(YEAR,-1,@date2)),23))
where winame in('pH值','渾濁度','臭和味','氨氮','游離余氯','總余氯','細菌總數','總大腸菌群','') 

union

select '環比' h,charindex(','+RTRIM(cast(winame as varchar(100)))+ ',',',pH值,渾濁度,臭和味,氨氮,游離余氯,總余氯,細菌總數,總大腸菌群,鋁')
,* from [dbo].[WaterQuality] (Convert(varchar(10),(Dateadd(MONTH,-1,@date1)),23),Convert(varchar(10),(Dateadd(MONTH,-1,@date2)),23))
where winame in('pH值','渾濁度','臭和味','氨氮','游離余氯','總余氯','細菌總數','總大腸菌群','')
order by h,charindex(','+RTRIM(cast(winame as varchar(100)))+ ',',',pH值,渾濁度,臭和味,氨氮,游離余氯,總余氯,細菌總數,總大腸菌群,鋁')

我原來三個語句,當前,同比,環比都寫了Order by  但是就不能union了,  所以我覺得Order by是應該寫在最后的。然后我排序的固定內容也寫在了select后面才得以實行

 

 21.判斷除數不能為0

Sql Server好像沒有判斷是否為0的函數,只有一個NULLIF可以用一下,這個是判斷如果是0就設置為NULL,還可以用

1/NULLIF(列名,0)

 

22. 一個表的數據查詢結果插入另外一個表

insert into VaeDB.dbo.A(Name)  select Name from B group by Name

 

23. Sql Server修改查詢結果

 

使用編輯查詢結果的方式,適合小數據量的時候,有時候不想寫update語句

先在表上點擊編輯前200行,然后選擇顯示SQL窗格,如圖

這個時候直接輸入sql語句,查詢的結果可以在下面直接修改,少量數據還是很方便的

 

24.去除所有重復的數據,或者得到所有不重復的數據,使用的是group by和having的組合搭配,巧妙的是min函數,這樣重復的數據我只拿第一個,這不就不重復了嗎

網上全都是介紹distinct的,這個distinct不好用,只能看一列數據,沒用而且效率很低

--這個是所有不重復的數據
select ReplaceProductName, min(ProductAlterId) as minProductAlterId from ProductAlter group by ReplaceProductName having COUNT(ReplaceProductName)>=1 order by minProductAlterId

--這個是所有重復的數據
select * from ProductAlter a inner join (
select ReplaceProductName, min(ProductAlterId) as minProductAlterId from ProductAlter group by ReplaceProductName having COUNT(ReplaceProductName)>1 ) as aa
on a.ReplaceProductName=aa.ReplaceProductName and a.ProductAlterId<>aa.minProductAlterId order by a.ProductAlterId

 

25. 去除字段中所有的空格

單純的使用Ltrim或者Rtrim有時候是不行的,因為空格中存在換行符,回車等,所以要先替換掉這些特殊字符,再去除空格

LTRIM(RTRIM(REPLACE(REPLACE( 字段A,char(13),''),char(10),'') ))

 

26.傳遞給 LEFT 或 SUBSTRING 函數的長度參數無效。

我在使用SUBSTRING方法的時候報了上面的錯誤,原因是因為這個字段得需要判斷一下是否包含這個字符,例如

select SUBSTRING(PartNumber,0,CHARINDEX('-',PartNumber)-1) from dbo.Series

上面這個就是錯誤的,因為PartNumber字段里面可能有不包含 -  的數據,所以就報錯了,正確的做法是再加一個判斷,如下

select SUBSTRING(PartNumber,0,CHARINDEX('-',PartNumber)-1) from dbo.Series where CHARINDEX('-',PartNumber) > 0

 


免責聲明!

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



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