吐血记录的sql问题

最近要用sql了,丢了一年多了,才发现好多基础的东西都忘了,要死!赶紧记录加强记忆。

1.if 后面的判断条件是boolean型的,如果是值判断要用exists()

IF EXISTS(SELECT 1 FROM dbo.tbl WHERE dDate='2020-07-01') 	
	BEGIN
	BREAK
	END
ELSE 
	BEGIN
	break
	end

2.proc中 create proc 要是第一行语句,最好前后加个GO,@a int是输入变量,declear @a int是内部变量,@a int outer是输出变量。

CREATE PROCEDURE [dbo].[P_Max]
@a int, -- 输入
@b int, -- 输入
@Returnc int output --输出
AS 

if (@a>@b) 
   set @Returnc =@a
else
   set @Returnc =@b

-- 调用
declare @Returnc int 
exec P_Max  2,3,@Returnc output 
select @Returnc

3.while 里面不加begin end 的话会死循环!

DECLARE @a INT,@b INT;
SET @a =1 
SET @b=1
PRINT @a
WHILE @a <10
	begin   --去掉就死循环
	SELECT @a
	SELECT @b
	SET @a+=1
	SET @b+=1
	END     --去掉就死循环

4.创建自增字段
另外有个BIGINT数据类型2^63-1

SELECT IDENTITY(INT,1,1) AS fid ,* INTO temcopy FROM a

5break好像只能用在while里面,其他地方可以用return。
自增字段要编辑的话方法如下:

SET IDENTITY_INSERT TABLE_NAME ON;

INSERT INTO TABLE_NAME(XXX, XXX,…, XXX) SELECT XXX, XXX,…, XXX FROM TABLE_NAME_BAK;

注意: 即使是所有列,这里的字段名也不能省略.

SET IDENTITY_INSERT TABLE_NAME OFF;

6左/右去空格 ltrim()/rtrim()。如果是中间去空格用replace(好像没有trim()),另外空格生成一个空格可以用space(1)

SELECT REPLACE(('ni'+'hao'+str(5)),SPACE(1),'')

7 for xml path 的用途:
引:https://www.cnblogs.com/wangjingblogs/archive/2012/05/16/2504325.html
1.变成xml格式
select * from a for xml path
2.xml行节点名变更
select * from a for xml path(‘行节点名’)
3.屏蔽行列名,只显示结果
SELECT ‘[ ‘+hName+’ ]’ FROM @hobby FOR XML PATH(‘’)
这里的path(‘’)应该就是设置行节点为空
3.筛选及多列合并字段

--备注订单号,订单号按','隔开
--stuff的作用是去除第一逗号,如果用substring或者left或者right则需要再嵌套一层select进行筛选
select 单据日期, 销售订单号 = (stuff((select distinct ',' + 销售订单号 from #tempfin where 单据日期 = 
    a.单据日期 for xml path('')),1,1,'')) 
    INTO #temporder
    from #tempfin a group by 单据日期

8修改一个表中一列为自增列。
直接改可能不行,这时会有2种方案。
一种是先删除id列,再新建一个id自增列。

alter table 表名 drop column ID

alter table 表名 add ID int identity(1,1)

一种是通过ssms修改
在这里插入图片描述
如果保存时报错把以下选择项去掉就行。
在这里插入图片描述
9 将截断字符串或二进制数据。
出现这个提示是说你update的字段长度过短,而更新的内容过长,一般直接修改set前的字段长度,或者用’000000000000000’ as 字段,这种形式也可以。

	  SELECT 发货单号,'0000000000000'AS a ,'0000000000000'AS b,
	  '00000000000000000'AS date1,'000000000000000'AS date2
	  INTO #temptime3
	  FROM #temptime2 

10proc里面在插入临时表数据时select * into from 可能sum() group by 不会生效,可以退而求其次,分两步走,先select * into from 然后再新建一个临时表 select * into from 再sum() group by

11游标
转:https://www.cnblogs.com/qqhfeng/p/5348439.html

12分类汇总
注意grouping和with rollup 的组合

   SELECT  case when grouping([月份])=1 then '合计' else [月份] end as [月份]
      ,sum([采购入库])
      ,sum([其他入库])
      ,sum([销售出库])
      ,sum([其他出库])
   FROM [report].[dbo].[finance_cheng_zhi6]
  group by [月份]

      with rollup 

13时间处理

--本月1号

select dateadd(mm,DATEDIFF(mm,0,getdate()),0)

--本月最后一天

select dateadd(mm,DATEDIFF(mm,0,getdate())+1,-1)

--上个月1号

select dateadd(mm,DATEDIFF(mm,0,getdate())-1,0)

--上个月最后一天

select dateadd(mm,DATEDIFF(mm,0,getdate()),-1)

--下个月1号

select dateadd(mm,DATEDIFF(mm,0,getdate())+1,0)

--下个月最后一天

select dateadd(mm,DATEDIFF(mm,0,getdate())+2,-1)

14视图排序
报这个错:除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。
用top percent 似乎是无效的,虽然不会报错但实际还是没排序。
需要用top 1000000。

15proc里变量使用问题
如在非表头位置使用变量,直接使用即可,如@i,如果要在表头或者截断部分插入变量则要用@sql的形式。
如 create table ‘生产报表’+@i+‘月’,要set @tablename= ‘生产报表’+@i+‘月’,然后set @sql=‘create table ‘+@tablename+’’ ,最后exec(@sql)
另外强调一个细节问题,在@sql里进行如日期这种转换,一定要把convert写在里面!!!!!!!在外部转是无效的。。。。
如 a.日期 between ‘+convert(date,@time)+’ and convert(date,‘’‘+@time+’‘’)
and 后面的写法才有效!!,between后面这种实际没有转!!
并且convert里面要加两个引号’’
并且convert里面要加两个引号’’
并且convert里面要加两个引号’’
重要事情说三遍!这两个坑搞了一下午。。。。

16 用于proc中临时表里面筛选排序的row_number(),需要和over()一起使用,用于增加行号和分区。
其中:PARTITION BY 用于分区,不填就一个区 ,ORDER BY 用于排序。

SELECT ROW_NUMBER()OVER(PARTITION BY id ORDER BY id) 增加行号,* FROM dbo.group1

在这里插入图片描述
17 关于以下几个概念:
主键:一个表只能有一个的唯一非空字段,自带唯一索引。
外键:a表(主表)建好主键后,b表(从表)字段(是不是主键都行)关联引用a表的主键创建的为外键。不带索引。外键主要控制b表增删。
主键和索引:主键肯定是索引,索引不一定是主键。
索引:创建在一个或多个字段上,就像书的目录一样有利于表的查询(如果正确使用)。注意创建原则,可以百度,一般是查的多的字段加索引,改的多的字段不加。
聚集(簇集)索引和非聚集(簇类)索引:聚集索引是物理上对应分配的单表唯一索引,非聚集索引是分配单元(存储数据的单元)外套娃的索引。举例就是:聚集索引数据1,2,3,4在物理存储单元时会按照1,2,3,4的顺序存储,非聚集索引数据1,2,3,4在物理上就可能是3,2,1,4,只在逻辑上连续物理存储时不连续,非聚集索引指向的可能是另一个索引而不是数据本身。

索引调优:一般索引碎片5%以下不管,30%以下就重新组织,30%以上就重新生成。通过下面的代码能查:

--这个查询出的id填到下面11的位置。
SELECT DB_ID()
--主要是从下表查碎片信息,avg_fragmentation_in_percent
SELECT b.name,b.id,b.xtype,a.* FROM sys.dm_db_index_physical_stats (11, NULL, NULL , NULL,'LIMITED') a
LEFT JOIN sysobjects b ON a.object_id=b.id
--这个查索引名字,注意不是sysindexes,中间有个点!这俩是两个表!!!
SELECT name,* FROM sys.indexes

下面这个就是实操了,千万别报错,另外先要备份和在测试服跑一下
ps:每次跑完一个库要drop #temp,有需要的自己可以做成proc

--先跑db_id(),找到id填到26的位置
SELECT DB_ID()

SELECT IDENTITY(INT,1,1) id ,* INTO #temp FROM (
select t.name tname,i.name indexname,s.avg_fragmentation_in_percent avgf from sys.tables t
   join sys.indexes i on i.object_id=t.object_id
   join sys.dm_db_index_physical_stats(26,NULL,null,null,'limited') s
    on s.object_id=i.object_id and s.index_id=i.index_id
WHERE s.index_type_desc<>'HEAP' ) a
--看看索引情况
--SELECT * FROM #temp
--drop table #temp
--下面执行到end
DECLARE @i INT 
DECLARE @sql NVARCHAR(3000)
DECLARE @tablename NVARCHAR(150)
DECLARE @indexname NVARCHAR(150)
SET @i=1
SET @sql=''
WHILE @i<=(SELECT MAX(id) FROM #temp)
	BEGIN		
	
	IF (SELECT avgf FROM #temp WHERE id=@i) BETWEEN 10 AND 30
		BEGIN

		SET @tablename=(SELECT tname FROM #temp WHERE id=@i)
		SET @indexname=(SELECT indexname FROM #temp WHERE id=@i)
		SET @sql='alter index '+rtrim(@indexname)+' on dbo.'+quotename(rtrim(@tablename))+' reorganize'
		EXEC(@sql)
		PRINT(@i)
		end
		
	IF (SELECT avgf FROM #temp WHERE id=@i) > 30
		BEGIN

		SET @tablename=(SELECT tname FROM #temp WHERE id=@i)
		SET @indexname=(SELECT indexname FROM #temp WHERE id=@i)
		SET @sql='alter index '+rtrim(@indexname)+' on dbo.'+quotename(rtrim(@tablename))+' rebuild'
		EXEC(@sql)
		PRINT(@i)
		end
	
	SET @i+=1
END

--SELECT name,* FROM sys.indexes


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值