1. 程式人生 > >一些非常有用的SQL技巧

一些非常有用的SQL技巧

一、 只複製一個表結構,不復制資料

select top 0 * into [t1] from [t2]

二、 獲取資料庫中某個物件的建立指令碼

1、 先用下面的指令碼建立一個函式


if exists(select 1 from sysobjects where id=object_id('fgetscript') and objectproperty(id,'IsInlineFunction')=0)
drop function fgetscript
go

create function fgetscript(
@servername varchar(50)    --伺服器名
,@userid varchar(50)='sa'    --使用者名稱,如果為nt驗證方式,則為空
,@password varchar(50)=''    --密碼
,@databasename varchar(50)    --資料庫名稱
,@objectname varchar(250)    --物件名

) returns varchar(8000)
as
begin
declare @re varchar(8000)        --返回指令碼
declare @srvid int,@dbsid int      --定義伺服器、資料庫集id
declare @dbid int,@tbid int        --資料庫、表id
declare @err int,@src varchar(255), @desc varchar(255) --錯誤處理變數

--建立sqldmo物件
exec @err=sp_oacreate 'sqldmo.sqlserver',@srvid output
if @err <>0 goto lberr

--連線伺服器
if isnull(@userid,'')='' --如果是 Nt驗證方式
begin
  exec @err=sp_oasetproperty @srvid,'loginsecure',1
  if @err <>0 goto lberr

  exec @err=sp_oamethod @srvid,'connect',null,@servername
end
else
  exec @err=sp_oamethod @srvid,'connect',null,@servername,@userid,@password

if @err <>0 goto lberr

--獲取資料庫集
exec @err=sp_oagetproperty @srvid,'databases',@dbsid output
if @err <>0 goto lberr

--獲取要取得指令碼的資料庫id
exec @err=sp_oamethod @dbsid,'item',@dbid output,@databasename
if @err <>0 goto lberr

--獲取要取得指令碼的物件id
exec @err=sp_oamethod @dbid,'getobjectbyname',@tbid output,@objectname
if @err <>0 goto lberr

--取得指令碼
exec @err=sp_oamethod @tbid,'script',@re output
if @err <>0 goto lberr

--print @re
return(@re)

lberr:
exec sp_oageterrorinfo NULL, @src out, @desc out
declare @errb varbinary(4)
set @errb=cast(@err as varbinary(4))
exec master..xp_varbintohexstr @errb,@re out
set @re='錯誤號: '[email protected]
  +char(13)+'錯誤源: '[email protected]
  +char(13)+'錯誤描述: '[email protected]
return(@re)
end
go


2、 用法如下
用法如下,

print dbo.fgetscript('伺服器名','使用者名稱','密碼','資料庫名','表名或其它物件名')

3、 如果要獲取庫裡所有物件的指令碼,如如下方式


declare @name varchar(250)
declare #aa cursor for
select name from sysobjects where xtype not in('S','PK','D','X','L')
open #aa
fetch next from #aa into @name
while @@fetch_status=0
begin
print dbo.fgetscript('onlytiancai','sa','sa','database',@name)
fetch next from #aa into @name
end
close #aa
deallocate #aa

4、 宣告,此函式是csdn鄒建鄒老大提供的
三、 分隔字串
如果有一個用逗號分割開的字串,比如說"a,b,c,d,1,2,3,4",如何用t-sql獲取這個字串有幾個元素,獲取第幾個元素的值是多少呢?因為t-sql裡沒有split函式,也沒有陣列的概念,所以只能自己寫幾個函數了。
1、 獲取元素個數的函式


create function getstrarrlength (@str varchar(8000))
returns int
as
begin
  declare @int_return int
  declare @start int
  declare @next int
  declare @location int
  select @str =','+ @str +','
  select @str=replace(@str,',,',',')
  select @start =1
  select @next =1
  select @location = charindex(',',@str,@start)
  while (@location <>0)
  begin
    select @start = @location +1
    select @location = charindex(',',@str,@start)
    select @next [email protected] +1
  end
select @int_return = @next-2
return @int_return
end

2、 獲取指定索引的值的函式


create function getstrofindex (@str varchar(8000),@index int =0)
returns varchar(8000)
as
begin
  declare @str_return varchar(8000)
  declare @start int
  declare @next int
  declare @location int
  select @start =1
  select @next =1 --如果習慣從0開始則select @next =0
  select @location = charindex(',',@str,@start)
  while (@location <>0 and @index > @next )
  begin
    select @start = @location +1
    select @location = charindex(',',@str,@start)
    select @next [email protected] +1
  end
  if @location =0 select @location =len(@str)+1 --如果是因為沒有逗號退出,則認為逗號在字串後
  select @str_return = substring(@str,@start,@location [email protected]) [email protected]肯定是逗號之後的位置或者就是初始值1
  if (@index <> @next ) select @str_return = '' --如果二者不相等,則是因為逗號太少,或者@index小於@next的初始值1。
  return @str_return
end

3、 測試


SELECT [dbo].[getstrarrlength]('1,2,3,4,a,b,c,d')
SELECT [dbo].[getstrofindex]('1,2,3,4,a,b,c,d',5)

四、 一條語句執行跨越若干個資料庫
我要在一條語句裡操作不同的伺服器上的不同的資料庫裡的不同的表,怎麼辦呢?
第一種方法:


select * from OPENDATASOURCE('SQLOLEDB','Data Source=遠端ip;User ID=sa;Password=密碼').庫名.dbo.表名

第二種方法:
先使用聯結伺服器:


EXEC sp_addlinkedserver '別名','','MSDASQL',NULL,NULL,'DRIVER={SQL Server};SERVER=遠端名;UID=使用者;PWD=密碼;'
exec sp_addlinkedsrvlogin  @rmtsrvname='別名',@useself='false',@locallogin='sa',@rmtuser='sa',@rmtpassword='密碼'
GO

然後你就可以如下:


select * from 別名.庫名.dbo.表名
insert 庫名.dbo.表名 select * from 別名.庫名.dbo.表名
select * into 庫名.dbo.新表名 from 別名.庫名.dbo.表名
go

五、 怎樣獲取一個表中所有的欄位資訊
蛙蛙推薦:怎樣獲取一個表中所有欄位的資訊
先建立一個檢視


Create view fielddesc   
as
select o.name as table_name,c.name as field_name,t.name as type,c.length as

length,c.isnullable as isnullable,convert(varchar(30),p.value) as desp
from syscolumns c 
join systypes t on c.xtype = t.xusertype
join sysobjects o on o.id=c.id
left join    sysproperties p on p.smallid=c.colid and p.id=o.id   
where o.xtype='U'


查詢時:


Select * from fielddesc where table_name = '你的表名'


還有個更強的語句,是鄒建寫的,也寫出來吧


SELECT
(case when a.colorder=1 then d.name else '' end) N'表名',
a.colorder N'欄位序號',
a.name N'欄位名',
(case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '√'else '' end) N'標識',
(case when (SELECT count(*)
FROM sysobjects
WHERE (name in
          (SELECT name
          FROM sysindexes
          WHERE (id = a.id) AND (indid in
                    (SELECT indid
                  FROM sysindexkeys
                  WHERE (id = a.id) AND (colid in
                            (SELECT colid
                            FROM syscolumns
                            WHERE (id = a.id) AND (name = a.name))))))) AND
        (xtype = 'PK'))>0 then '√' else '' end) N'主鍵',
b.name N'型別',
a.length N'佔用位元組數',
COLUMNPROPERTY(a.id,a.name,'PRECISION') as N'長度',
isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0) as N'小數位數',
(case when a.isnullable=1 then '√'else '' end) N'允許空',
isnull(e.text,'') N'預設值',
isnull(g.[value],'') AS N'欄位說明'
--into ##tx

FROM  syscolumns  a left join systypes b
on  a.xtype=b.xusertype
inner join sysobjects d
on a.id=d.id  and  d.xtype='U' and  d.name <>'dtproperties'
left join syscomments e
on a.cdefault=e.id
left join sysproperties g
on a.id=g.id AND a.colid = g.smallid 
order by object_name(a.id),a.colorder


六、 時間格式轉換問題
因為新開發的軟體需要用一些舊軟體生成的一些資料,在時間格式上不統一,只能手工轉換,研究了一下午寫了三條語句,以前沒怎麼用過convert函式和case語句,還有"+"操作符在不同上下文環境也會起到不同的作用,把我搞暈了要,不過現在看來是差不多弄好了。

1、把所有"70.07.06"這樣的值變成"1970-07-06"


UPDATE lvshi
SET shengri = '19' + REPLACE(shengri, '.', '-')
WHERE (zhiyezheng = '139770070153')


2、在"1970-07-06"裡提取"70","07","06"


SELECT SUBSTRING(shengri, 3, 2) AS year, SUBSTRING(shengri, 6, 2) AS month,
      SUBSTRING(shengri, 9, 2) AS day
FROM lvshi
WHERE (zhiyezheng = '139770070153')

3、把一個時間型別欄位轉換成"1970-07-06"


UPDATE lvshi
SET shenling = CONVERT(varchar(4), YEAR(shenling))
      + '-' + CASE WHEN LEN(MONTH(shenling)) = 1 THEN '0' + CONVERT(varchar(2),
      month(shenling)) ELSE CONVERT(varchar(2), month(shenling))
      END + '-' + CASE WHEN LEN(day(shenling)) = 1 THEN '0' + CONVERT(char(2),
      day(shenling)) ELSE CONVERT(varchar(2), day(shenling)) END
WHERE (zhiyezheng = '139770070153')

七、 分割槽檢視
分割槽檢視是提高查詢效能的一個很好的辦法


--看下面的示例

--示例表
create table tempdb.dbo.t_10(
id int primary key check(id between 1 and 10),name varchar(10))

create table pubs.dbo.t_20(
id int primary key check(id between 11 and 20),name varchar(10))

create table northwind.dbo.t_30(
id int primary key check(id between 21 and 30),name varchar(10))
go

--分割槽檢視
create view v_t
as
select * from tempdb.dbo.t_10
union all
select * from pubs.dbo.t_20
union all
select * from northwind.dbo.t_30
go

--插入資料
insert v_t select 1 ,'aa'
union  all select 2 ,'bb'
union  all select 11,'cc'
union  all select 12,'dd'
union  all select 21,'ee'
union  all select 22,'ff'

--更新資料
update v_t set name=name+'_更新' where right(id,1)=1

--刪除測試
delete from v_t where right(id,1)=2

--顯示結果
select * from v_t
go

--刪除測試
drop table northwind.dbo.t_30,pubs.dbo.t_20,tempdb.dbo.t_10
drop view v_t

/**//*--測試結果

id          name     
----------- ----------
1          aa_更新
11          cc_更新
21          ee_更新

(所影響的行數為 3 行)
==*/


八、 樹型的實現


--參考

--樹形資料查詢示例
--作者: 鄒建

--示例資料
create table [tb]([id] int identity(1,1),[pid] int,name varchar(20))
insert [tb] select 0,'中國'
union  all  select 0,'美國'
union  all  select 0,'加拿大'
union  all  select 1,'北京'
union  all  select 1,'上海'
union  all  select 1,'江蘇'
union  all  select 6,'蘇州'
union  all  select 7,'常熟'
union  all  select 6,'南京'
union  all  select 6,'無錫'
union  all  select 2,'紐約'
union  all  select 2,'舊金山'
go

--查詢指定id的所有子
create function f_cid(
@id int
)returns @re table([id] int,[level] int)
as
begin
declare @l int
set @l=0
insert @re select @id,@l
while @@rowcount>0
begin
  set @[email protected]+1
  insert @re select a.[id],@l
  from [tb] a,@re b
  where a.[pid]=b.[id] and b.[level][email protected]
end
/**//**//**//*--如果只顯示最明細的子(下面沒有子),則加上這個刪除
delete a from @re a
where exists(
  select 1 from [tb] where [pid]=a.[id])
--*/
return
end
go

--呼叫(查詢所有的子)
select a.*,層次=b.[level] from [tb] a,f_cid(2)b where a.[id]=b.[id]
go

--刪除測試
drop table [tb]
drop function f_cid
go


九、 排序問題

CREATE TABLE [t] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[GUID] [uniqueidentifier] NULL
) ON [PRIMARY]
GO

下面這句執行5次


insert t values (newid())

檢視執行結果


select * from t

1、 第一種


select * from t
order by case id when 4 then 1
                  when 5 then 2
                  when 1 then 3
                  when 2 then 4
                  when 3 then 5 end

2、 第二種


select * from t order by (id+2)%6

3、 第三種


select * from t order by charindex(cast(id as varchar),'45123')

4、 第四種


select * from t
WHERE id between 0 and 5
order by charindex(cast(id as varchar),'45123')

5、 第五種


select * from t order by case when id >3 then id-5 else id end

6、 第六種


select * from t order by id / 4 desc,id asc


十、 一條語句刪除一批記錄
首先id列是int標識類型別,然後刪除ID值為5,6,8,9,10,11的列,這裡的cast函式不能用convert函式代替,而且轉換的型別必須是varchar,而不能是char,否則就會執行出你不希望的結果,這裡的"5,6,8,9,10,11"可以是你在頁面上獲取的一個chkboxlist構建成的值,然後用下面的一句就全部刪
除了,比迴圈用多條語句高效吧應該。


delete from [fujian] where charindex(','+cast([id] as varchar)+',',','+'5,6,8,9,10,11,'+',')>0

還有一種就是


delete from table1 where id in(1,2,3,4 )

十一、獲取子表內的一列資料的組合字串
下面這個函式獲取05年已經註冊了的某個所的律師,唯一一個引數就是事務所的名稱,然後返回zhuce欄位裡包含05字樣的所有律師。


CREATE  FUNCTION fn_Get05LvshiNameBySuo  (@p_suo Nvarchar(50))
RETURNS Nvarchar(2000)
AS
BEGIN 
DECLARE @LvshiNames varchar(2000), @name varchar(50)
select @LvshiNames=''
DECLARE lvshi_cursor CURSOR FOR
資料庫裡有1,2,3,4,5 共5條記錄,要用一條sql語句讓其排序,使它排列成4,5,1,2,3,怎麼寫? 

相關推薦

一些非常有用SQL技巧

一、 只複製一個表結構,不復制資料 select top 0 * into [t1] from [t2] 二、 獲取資料庫中某個物件的建立指令碼 1、 先用下面的指令碼建立一個函式 if exists(select 1 from sysobjects where i

推薦一些非常有用的學習網站

昨天的文章很多人表示很受用,同時有人留言讓我推薦一些學習渠道啥的,馬上雙 11,姑且忙中偷閒送波福利給你們,今天就給你們推薦一些絕對有用的學習網站。 1. free-programming-books這個就不多說了,之前有推薦過的,免費的計算機程式設計類書籍,很多很全,不過都是英文的,有英語閱讀習慣的人強烈

施工測量中Cad一些非常有用的外掛

經常會遇到座標在cad中批量展點、從cad中批量儲存座標點、匯入cad中的座標怎麼才能有點號,怎麼快速標註cad裡的座標點··· ··· 這一切都是可以程式化的,cad是可以二次開發的,我經常用易語言進行cad二次開發,來方便我工作中繁瑣重複的工作。解放我的雙手,提高我的效率。 一、怎麼快速標註cad裡的

12個非常有用的javascript技巧,必看!

login 他會 有時 throw 代碼 取數 屬性 nbsp 存在 提示:該文章是整理別人別人的文章,作者比較多,很難分辨原創作者是誰。 1)使用!!將變量轉換成布爾類型   有時,我們需要檢查一些變量是否存在,或者它是否具有有效值,從而將他們的值視為true。對於這樣的

非常有用sql腳本

_cmd 自動 while sts where end print style ins /*sql 語法學習*//*函數的學習---------------------------------------*/獲取當前時間(時/

12 個非常有用的 JavaScript 技巧

在這篇文章中將給大家分享12個有關於JavaScript的小技巧。這些小技巧可能在你的實際工作中或許能幫助你解決一些問題。 使用!!操作符轉換布林值 有時候我們需要對一個變數查檢其是否存在或者檢查值是否有一個有效值,如果存在就返回true值。為了做這樣的驗證,我們可

mysql的sql執行計劃詳解(非常有用

引言: 實際專案開發中,由於我們不知道實際查詢的時候資料庫裡發生了什麼事情,資料庫軟體是怎樣掃描表、怎樣使用索引的,因此,我們能感知到的就只有 sql語句執行的時間,在資料規模不大時,查詢是瞬間的,因此,在寫sql語句的時候就很少考慮到效能的問題。但是當資料規模增大,

SQL中-分組拼接-某列的方法_ORACLE(對於做echarts等圖表的資料返回格式非常有用!!)

函式名:wm_concat(XX);(注意:ORACLE10g及以上版本支援) 分組拼接前: 分組拼接後: 得到以','隔開的字串.最後處理下可以得到對應陣列.解決echarts的折線圖等返回資料格式問題.要比寫演算法輕鬆的多. select tt.name,

一些非常有用原始碼分享(百度指數破解(最新版),NDIS實現類似P2P終結者功能程式碼,GOOGLE線上翻譯等等)

最近自己要去深圳,開始人生的第二份工程,所以整理以前自己寫過的小玩意程式碼(跟自己工作的程式碼無關),自己下班回家寫的程式碼,準備解除安裝簡歷裡面去求職。程式碼風格自己有注意,但還是每次看自己以前寫的程式碼就感覺是那麼醜。 1:NDIS實現類似P2P終結者的核心程式碼

MySQL一些SQL技巧

1,一行轉多行      url列以分號分隔,將其一行轉化為多行,藉助自增長表help_topic 實現。select a.channel_id,channel_code,site_name,sitei

經典sql語句大全-非常有用(特指Mysql)

7、說明:新增主鍵: Alter table tabname add primary key(col) 說明:刪除主鍵: Alter table tabname drop primary key(col) 8、說明:建立索引:create [unique] index idxname on tabname(c

與postgis相關的一些常用的sql

geo value lec insert type point nes table null create table NODES (ID SERIAL not null,geometry geography(POINTZ, 4326) null); create tab

sql技巧】mysql修改時,動態指定要修改的字段 update `table` set (case when ....) = 1 where id = xx

幫助 ase stack pan 希望 需求 記錄 開始 lec 如果你點進了這篇帖子,那麽你一定遇到了跟我一樣的問題。別看題目的set case when...,我一開始也是第一反應是用case when但是發現並不好使。 問題呢,說得高大上一點:動態指定要修改的字段。

性能測試常用sql技巧_Oracle

star for 語句 計數 性能 table 實現 creator 自己   做了一段時間的性能測試,把自己在性能測試過程中,使用到的Oracle中用到的sql語句整理一番,做個備忘; (1)多個字段以某種格式拼接   "||"字符串拼接符;   示例:將“id”及“co

剛開始學習的人非常有用:struts2中將jsp數據傳到action的幾種方式

登錄頁面 sign config print log println amp war htm 先給上struts.xml代碼: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBL

或許你不知道的10條SQL技巧

提高效率 經驗 查詢 中國 nbsp 結果集 復雜 移動 前綴 這幾天在寫索引,想到一些有意思的TIPS,希望大家有收獲。 一、一些常見的SQL實踐 (1)負向條件查詢不能使用索引 select * from order where status!=0 and st

一些mysql的sql語句

max type 西湖 管理員 order by tree 便宜 信息 user SELECT hou.*,uname FROM hos_house AS hou INNER JOIN sys_user AS usr INNER JOIN hos_type AS hty O

一些拿shell的技巧

漏洞 有時 例如 strong 空格 -1 根目錄 找到 代碼 轉自: 一些拿shell的技巧 1.直接上傳asp asa jsp cer php aspx htr cdx 格式的木馬,不行就加個空格或是利用IIS6.0解析漏洞,常見格式:1.asp;1.jpg 或 1.a

sql技巧(增冊改查)

int -1 modify 類型 插入 nbsp alter channel employ 1 select * from wyl.t; 2 --將數據從t1導入t2 3 insert into t2(c1,c2) select c1,c2 from t1 w

非常有用的GitHub鏈接

ont cor 文件中 put pau mda bst 書籍 程序 平常開發工作中,我經常取Github上搜索項目,Clone下來學習使用,在這個過程中,發現了好多比較好的Github地址,記錄下來,分享出去。 image 非常有用的GitHub鏈接