SQL常用方法及问题处理

1、数据相关操作
1、数据取整截取
【四舍五入取整截取】

select round(54.56,0)

 【向下取整截取】 得54

SELECT FLOOR(54.56)

 【向上取整截取】 得14

 SELECT   CEILING(13.15)
2、 报错:遇到以零作除数错误
 1、在除数那里判断分母是否为0(用‘NULLIF’函数)
 select FLOOR(MB038/NULLIF(MB037,0)/11.5) AS XSCN from INVMB
 2、在除数那里判断分母是否为0(用‘CASE WHEN’函数)
 SELECT (CASE WHEN Quantity*UnitPrice=0 THEN 0 ELSE (Quantity*Price)/(Quantity*UnitPrice)) AS [平均值]   FROM ##表 
2、日期相关操作
1、格式转换
Select CONVERT(varchar(100), GETDATE(), 20): 2006-05-16 10:57:47
Select CONVERT(varchar(100), GETDATE(), 21): 2006-05-16 10:57:47.157
Select CONVERT(varchar(100), GETDATE(), 23): 2006-05-16
Select CONVERT(varchar(100), GETDATE(), 24): 10:57:47
Select CONVERT(varchar(100), GETDATE(), 102): 2006.05.16
Select CONVERT(varchar(100), GETDATE(), 111): 2006/05/16
Select CONVERT(varchar(100), GETDATE(), 112): 20060516
Select CONVERT(varchar(100), GETDATE(), 120): 2006-05-16 10:57:49
select datediff(year, 开始日期,结束日期); --两日期间隔年
select datediff(quarter, 开始日期,结束日期); --两日期间隔季
select datediff(month, 开始日期,结束日期); --两日期间隔月
select datediff(day, 开始日期,结束日期); --两日期间隔天
select datediff(week, 开始日期,结束日期); --两日期间隔周
select datediff(hour, 开始日期,结束日期); --两日期间隔小时
select datediff(minute, 开始日期,结束日期); --两日期间隔分
select datediff(second, 开始日期,结束日期); --两日期间隔秒
2、取第一天
1) 一年的第一天
      SELECT DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE()),0)
      注:首先DATEDIFF(YEAR,0,GETDATE()) --计算当前年份与 1900年相差的年数,然后通过计算1900-1-1加上相差的年数的日期即为当年第一天
2) 一个季的第一天
   SELECT DATEADD(Quarter,DATEDIFF(Quarter,0,GETDATE()),0)
      注:首先DATEDIFF(Quarter,0,GETDATE()) --计算当前月份与 1900年相差的季份数,然后通过计算1900-1-1加上相差的季份数的日期即为当季第一天
3) 一个月的第一天
      SELECT DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE()),0)
     注:首先DATEDIFF(MONTH,0,GETDATE()) --计算当前月份与 1900年相差的月份数,然后通过计算1900-1-1加上相差的月份数的日期即为当月第一天
4) 一周的第一天
   SELECT DATEADD(wk,DATEDIFF(wk,0,GETDATE()),0)  
5) 当天的半夜 (00:00:00.000)
      SELECT DATEADD(DAY,DATEDIFF(DAY,0,GETDATE()),0)     
6) 上月的最后一天
   SELECT DATEADD(ms,-3,DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE()),0))
      注:用本月的第一天减去3毫秒,即得出上个月的最有一天.SQL SERVER DATETIME类型的时间精确到3毫秒。
7) 本月的最后一天
      SELECT DATEADD(ms,-3,DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE())+1,0))
8) 本月的天数
      i) SELECT DAY(DATEADD(ms,-3,DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE())+1,0)))
      ii)SELECT 32-DAY(GETDATE()+(32-DAY(GETDATE())))  
9) 本年的最后一天
      SELECT DATEADD(ms,-3,DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE())+1,0))
10) 一周的第一天
   SELECT DATEADD(DAY,1-DATEPART(weekday,GETDATE()),GETDATE())
   一周的最后一天
   SELECT DATEADD(DAY,7-DATEPART(WeekDay,GETDATE()),GETDATE())
     SELECT DATEADD(weekday,DATEDIFF(weekday,0,DATEADD(DAY,6-DATEPART(day,GETDATE()),GETDATE())),0)
3、字符串相关操作
1、统计字段中符号出现的次数。
len(字段)-len(replace(字段,'查找符号','')) AS gs
2、无法解决 equal to 操作中 “Chinese_PRC_CI_AS” 和 “Chinese_PRC_BIN” 之间的排序规则冲突
添加 collate Chinese_PRC_CI_AS 就行
如:from uf_workorderonline left join YFERP.RM.dbo.INVMB on cpph=MB001 collate Chinese_PRC_CI_AS
3、参数数据类型 text 对于 len 函数的参数 1 无效
1、参数数据类型 text 对于 len 函数的参数 1 无效,使用cast 把 text 先转为 varchar。
isnull(len(CAST(sxyg as VARCHAR(4000)))-len(replace(CAST(sxyg as VARCHAR(4000)),',',''))+1,0) AS sxyg
4、游标相关操作
	declare @sxsl int --上线数量
	declare @kdsj char(5) --开单时间
	declare @cpph varchar(200) --产品品号
	
	DECLARE JSQJHQLCURSOR CURSOR FOR  --创建游标 JSQJHQLCURSOR为游标名称
	SELECT cpph,sxsl,kdsj FROM uf_workorderonline 
	where kdrq = CONVERT(varchar(100), GETDATE(), 23) and cxbh=@SCCX order by id asc   --要循环的数据存入游标

	OPEN JSQJHQLCURSOR                 --打开游标   
	FETCH FROM JSQJHQLCURSOR INTO
	  @cpph,@sxsl,@kdsj    --取出数据存入临时变量中
	WHILE @@FETCH_STATUS=0  --进入循环
	BEGIN
		----------------------
			--这里是判断条件及操作
		-------------------
		FETCH NEXT FROM JSQJHQLCURSOR INTO  --执行下一条
		@cpph,@sxsl,@kdsj	
	END
	
	CLOSE JSQJHQLCURSOR 
	Deallocate JSQJHQLCURSOR	
5、两台SQL服务器相互访问
创建服务器的连接

EXEC sp_addlinkedserver
@server='name',--被访问的服务器别名
@srvproduct='',
@provider='SQLOLEDB',
@datasrc='192.168.3.X' --要访问的服务器

EXEC sp_addlinkedsrvlogin
'name', --被访问的服务器别名
'false',
NULL,
'sa', --帐号
'sa' --密码

查询方式

SELECT * FROM 服务器名.数据库名.dbo.表名

完成互联后必须执行第7 
6、清除数据库日志文件
USE [master]  
GO  
ALTER DATABASE [RM] SET RECOVERY SIMPLE WITH NO_WAIT  
GO  
ALTER DATABASE [RM] SET RECOVERY SIMPLE  
GO  
USE [RM]  
GO  
DBCC SHRINKFILE (N'Leader_Log' , 0,TRUNCATEONLY)  
GO  
USE [master]  
GO  
ALTER DATABASE [RM] SET RECOVERY FULL WITH NO_WAIT  
GO  
ALTER DATABASE [RM] SET RECOVERY FULL  
GO  
  
--查询指定数据库的日志文件名称  
USE [RM]   
GO  
SELECT name FROM SYS.database_files WHERE type_desc='LOG'  
7.做触发器时错误“该伙伴事务管理器已经禁止了它对远程/网络事务的支持”解决方案(两台SQL关联后必须确认该操作)

Server 2008 r2 操作系统
启动台下服务。
Distributed Transaction Coordinator
Distributed Link Tracking Client
Remote Procedure Call(PRC)
Remote Procedure Call(PRC) Locator

同时打开’控制面板’->‘管理工具’->‘组件服务’,点开’组件服务’->‘计算机’->‘我的电脑’,然后展开“我的电脑”,找到 Distributed Transaction Coordinator 继续展开,在

本地DTC上右键,属性。 勾选 安全设置所有选项和 不要求进行验证。

8、获取数据库表中所有的字段名称
declare @s nvarchar(4000)

select @s=isnull(@s+',','')+quotename(name) from syscolumns where id=OBJECT_ID('INVMB') #INVMB 数据库表

select @s  #@S 所有字段保存的临时字段
9、允许复制自增ID

SET IDENTITY_INSERT 表名XXX ON

SET IDENTITY_INSERT 表名XXX OFF

10、查询结果生成新数据表
select * into 新表 from 老表 where 查询条件
11、先进先出原则计算
--方法一
declare @dt datetime,@pid char(3)
set @dt='2004-01-06'
set @pid='001'

declare @p table ( pid char(3),iodt datetime, qty int)

insert @p select '001', '2004-01-01', 10
    union select '001', '2004-01-03', -8
    union select '001', '2004-01-04', -1
    union select '001', '2004-01-05',  5
    union select '001', '2004-01-07', -6
    union select '002', '2004-01-06', 20

select pid,库龄,case when qty>数量 then 数量 else qty end as 数量
from (  select pid,
               datediff(day,iodt,@dt) as 库龄,
               qty,
               (  select isnull(sum(qty),0) 
                      from @p 
                      where pid=@pid and iodt<=@dt and (iodt<=a.iodt or (iodt>a.iodt and qty<0))  
                   )
                 as 数量
        from @p a
        where pid=@pid and iodt<=@dt and qty>0
      ) b
where 数量>0

--方法二 需 SQL2012及以上版本或oracle才支持。
-- 20200719 日期作为变量传入
 
with p_dw as
 (select '001' pid, '20200701' date_id, 10 qty
    from dual
  union all
  select '001' pid, '20200703' date_id, -8 qty
    from dual
  union all
  select '001' pid, '20200704' date_id, -1 qty
    from dual
  union all
  select '001' pid, '20200705' date_id, 5 qty --3 
    from dual
  union all
  select '001' pid, '20200707' date_id, -3 qty
    from dual
  union all
  select '001' pid, '20200708' date_id, 9 qty --9 
    from dual
  union all
  select '001' pid, '20200709' date_id, 7 qty --7 
    from dual
  union all
  select '001' pid, '20200710' date_id, 7 qty --7 
    from dual)
select pid,
       --qty,
       date_id,
       days,
       current_store_nums cnt_qty,
       --nvl(lag(current_store_nums) over (partition by pid order by date_id),0) LAST_ROWS,
       current_store_nums -
       nvl(lag(current_store_nums) over(partition by pid order by date_id),
           0) current_store_row__qty
  from (select pid,
               qty,
               date_id,
               to_date('20200719', 'yyyymmdd') -
               to_date(date_id, 'yyyymmdd') days,
               SUM(case
                      when qty < 0 then
                       qty
                      else
                       0
                    end) OVER(PARTITION BY PID) + SUM(case
                 when qty > 0 then
                  qty
                 else
                  0
               end) OVER(PARTITION BY PID ORDER BY DATE_ID) current_store_nums
          from p_dw
         where date_id <= '20200719')
 WHERE current_store_nums > 0
   AND QTY > 0
12、SQL游标循环查询表值函数并存到指定表中
DECLARE @ph CHAR(20) 
DECLARE JSQJHQLCURSOR CURSOR FOR
		select 品号 from LED
	OPEN JSQJHQLCURSOR                    --循环取品号当条件传入,然后通过LOADBOM函数取材料品号
	FETCH FROM JSQJHQLCURSOR INTO
	  @ph
	WHILE @@FETCH_STATUS=0  --通过游标判断循环
	BEGIN 
	insert into LEDlist select distinct ID  from (  --把材料品号结果存入 LEDlist表中。
	SELECT ID FROM Loadbom(@ph,1) where ID<>@ph 
    union all
    SELECT ParentID FROM Loadbom(@ph,1) where ID<>@ph )as KK
    
		FETCH NEXT FROM JSQJHQLCURSOR INTO
		@ph
	END
	
	CLOSE JSQJHQLCURSOR 
	Deallocate JSQJHQLCURSOR
	
13、SQL中 TOP 与 TOP (100) PERCENT 的说明
sql="select top 30 * from data where title='"&title1&"' order by id desc" 原意是选出符合“where 条件”的记录集里的“前30条”

但是,对于该SQL语句,由于语句里同时存在where和top语句的,并且where条件列不是合适的索引,程序执行的是全表扫描,首先是查找符合where条件的记录, 而这里的top限制形同虚设。如果全表是百万级别以上的数据表,那么就这么一个简单的判断,就有可能拖垮数据库。

所以需要先把符合“where条件”的记录,用一个子查询筛选出来,再在筛选结果集里选top30。

因为SQL规则规定,如果子查询里,有order ...,就必须有TOP,所以就用SELECT TOP (100) PERCENT来限定,TOP (100) PERCENT是为了保证筛选出所有符合条件的数据条目。
PERCENT 代表的是 百分比
TOP (10) PERCENT 代表的是 10% 符合条件的数据
TOP (100) PERCENT 代表的是 100% 符合条件的数据
14、通过XML将字符串转换为表格列值
DECLARE @str VARCHAR(1000)
DECLARE @x xml
SET @str='aaa,bbb,ccc'
SELECT id
      FROM (SELECT [value] = CONVERT(XML , '<v>' + REPLACE(@str , ',' , '</v><v>')+ '</v>')
      ) A
      OUTER APPLY ( SELECT id = N.v.value('.' , 'varchar(100)')
                    FROM A.[value].nodes('/v') N (v)
                  ) B
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东枫落定

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值