SQL 数据库 知识总结

本文详细介绍了SQL Server数据库的基础知识,包括自定义类型、系统类型表、数据库架构、对象ID、存储过程参数设置、动态SQL执行、索引创建与优化、数据类型转换、查询优化技巧等内容,为数据库管理员和开发者提供了实用的指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

sqlserver

基础

1 创建别名和自定义类型

create type  AS ( attribute_name data_type [, ... ] )

2 系统类型表

每个系统类型和用户定义类型都在表中对应一行。

sys.types

3 数据库架构表

sys.schemas (Transact-SQL)

每个数据库架构都对应一行。

 架构是形成单个命名空间的数据库实体的集合。命名空间是一个集合,其中每个元素的名称都是唯一的。

比如dbo

系统表 

sysobjects
在数据库内创建的每个对象(约束、默认值、日志、规则、存储过程等)在表中占一行。只有在 tempdb 内,每个临时对象才在该表中占一行。

7 对象的唯一ID 

OBJECT_ID

返回架构范围内对象的数据库对象标识号。

系统给表分配的唯一ID  

object_id就是根据对象名称返回该对象的id.

8 数据库架构对象的相关信息

objectproperty (Transact-SQL)

返回当前数据库中架构范围内的对象的相关信息。 有关架构范围内对象的列表,请参阅 sys.objects (Transact-SQL)。 不能将此函数用于不属于架构范围内的对象,如数据定义语言 (DDL) 触发器和事件通知。

OBJECTPROPERTY ( id , property )

9 使 SQL Server 遵从关于引号分隔标识符和文字字符串的 ISO 规则

SET quoted_identifier (Transact-SQL)

当 SET QUOTED_IDENTIFIER 为 ON 时,标识符可以由双引号分隔,而文字必须由单引号分隔。当 SET QUOTED_IDENTIFIER 为 OFF 时,标识符不可加引号,且必须遵守所有 Transact-SQL 标识符规则。”

10  指定Null 值使用

SET ANSI_NULLS ON

指定在 SQL Server 2017 中与 Null 值一起使用等于 (=) 和不等于 (<>) 比较运算符时采用符合 ISO 标准的行为。

当 ANSI_NULLS 为 ON 时,即使 包含空值,使用 WHERE column_name = NULL 仍返回零行。 

当 ANSI_NULLS 为 OFF 时, 使用 WHERE column_name = NULL 的返回 包含空值的行。

11 设置传入存储过程参数为只读

READONLY

CREATE PROCEDURE a(   @a VARCHAR(10) READONLY)

12 设置默认参数

CREATE PROCEDURE a( @a VARCHAR(10)='')

13 加密

with encryption

进行加密,加密以后,别人看不到触发器或存储过程里面的t-sql语句内容

14 sys.all_parameters Transact-SQL

显示属于用户定义对象或系统对象的所有参数的并集。

扩展:

1 在sys.schemas中

  • schema_id  :架构的 ID。 在该数据库中是唯一的。
  •  name:名称

在sys.sysobjects中

  • xtype:对象类型 V = 视图   X = 扩展存储过程

在sys.all_parameters中

  • name 参数名,object_id:唯一ID,user_type_id:类型ID,is_output:参数为输出值

在sys.types中

  • user_type_id:类型 ID。 系统数据类型: user_type_id = system_type_id;.name:类型名称,string之类;is_table_type:是否为表格类型

 

name 参数名

3 N

object_id(N'表名')中N' 代表 Unicode类型.可以支持不同语种的对象名

4 判断某值存在

IF  EXISTS ( )
BEGIN
END

5 在OBJECTPROPERTY 中

id
是表示当前数据库中对象 ID 的表达式。 id 的数据类型为 int,并假定为当前数据库上下文中的架构范围内的对象。

property
一个表达式,提供 id 指定的对象的返回信息。

IsProcedure 过程

6 删除存储过程

drop procedure

7 去除字符串右边多余空格

RTRIM()函数,用于去除字符串右边多余的空格

8 查找字符串在目标字符串位置

 通过CHARINDEX如果能够找到对应的字符串,则返回该字符串位置,否则返回0。

CHARINDEX ( expressionToFind , expressionToSearch [ , start_location ] )

起始位置从1开始

截取一个栏位资料中的其中一部分。

substring('abdcsef',1,3)

起始位置从1开始

10 sql的left()函数表示的是从字符表达式最左边一个字符开始返回指定数目的字符

11 转化字符串为int: CONVERT(INT,str)

12 SET NOCOUNT 
使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。 

13 取日期

select day(createtime),month(createtime),year(createtime) from product     --取时间字段的天值,月值,年值

14 转化数据类型

CAST (expression AS data_type) 

expression:任何有效的SQServer表达式。AS:用于分隔两个参数,在AS之前的是要处理的数据,在AS之后是要转换的数据类型。data_type:目标系统所提供的数据类型,包括bigint和sql_variant,不能使用用户定义的数据类型。

15 between

在sqlerver 等价于   a>=min and  a<=max

16 自定义类型table必须要有对应字段的table传入

 比如SQL CREATE TYPE A AS TABLE(code NVARCHAR(255))

C#:    DataTable dt = new DataTable(); dt.Columns.Add(new DataColumn("code", Type.GetType("System.String")));

17 更改数据库的兼容级别

ALTER DATABASE CM2017 SET COMPATIBILITY_LEVEL = 100 

18 ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)

row_number()从1开始,为每一条分组记录返回一个数字,这里的ROW_NUMBER() OVER (ORDER BY xlh DESC) 是先把xlh列降序,再为降序以后的没条xlh记录返回一个序号。 

19 row_number() OVER (PARTITION BY COL1 ORDER BY COL2) 

表示根据COL1分组,在分组内部根据 COL2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)

20 SELECT id ,COUNT(1) count FROM table group by id

=  SELECT id ,COUNT(id) count FROM table group by id

partition  by关键字是分析性函数的一部分,它和聚合函数(如group by)不同的地方在于它能返回一个分组中的多条记录,而聚合函数一般只有一条反映统计值的记录,

partition  by用于给结果集分组,如果没有指定那么它把整个结果集作为一个分组。

partition by 与group by不同之处在于前者返回的是分组里的每一条数据,并且可以对分组数据进行排序操作。后者只能返回聚合之后的组的数据统计值的记录。

21     ROUND() – 四舍五入一个正数或者负数,结果为一定长度的值。            长度为1,就11.10
   CEILING() - 返回最小的整数,使这个整数大于或等于指定数的数值运算。 11.05 变为12 
   FLOOR() - 返回最大整数,使这个整数小于或等于指定数的数值运算。    11.05 变为11

22   DATENAME(YEAR,GETDATE()) 获取日期年份

       DATENAME(MONTH,GETDATE())  获取月份

动态SQL执行

普通SQL语句:(1)exec('select * from Student')

(2)exec sp_executesql N'select * from Student'--此处一定要加上N,否则会报错

2.带参数的SQL语句 (1)declare @sql nvarchar(1000) ,@userId varchar(100)
 set @userId='0001'    set @sql=N'select * from Student where UserID=@userId'
 exec sp_executesql @sql,N'@userId varchar(100)'

(3)带输出参数的SQL语句  declare @sql nvarchar(1000)

set @sql=N'select @userName=UserName from Student where UserId=1'

exec sp_executesql N'@userName varchar(100) output',@userName output ; select @userName

索引

索引提升查询速度

索引分类

唯一索引(UNIQUE):索引值唯一的(创建了唯一约束,系自动创建唯一索引)

主键索引:主键列,自动创建主键索引。

聚集索引(CLUSTERED):存储记录物理上连续,表的物理存储顺序。

非聚集索引(NONCLUSTERED): 存储记录物理上不连续,逻辑上连续。

UNIQUE:唯一索引。 clustered:聚集索引。nonclustered:非聚集索引。

创建索引:CREATE CLUSTERED INDEX Typeid ON #dtype(typeid) 

查询

设计同一部门的员工的时候编码可以设计为前几位相同,比如有两行数据 前几位相同

00003
0000300001

使用like 加join联查出前几位相同编号员工

SELECT a.typeId FROM dbo.Department a JOIN Department  b ON a.typeId LIKE b.typeId+'%'

使用分页:


1  ROW_NUMBER() OVER()方式 

select * from ( select *, ROW_NUMBER() OVER(Order by ArtistId ) AS RowId from ArtistModels ) as b where RowId between 10 and 20 

2  offset fetch next方式(SQL2012以上的版本才支持:推荐使用 )

select * from ArtistModels  order by ArtistId offset 4 rows fetch next 5 rows only

3 --top not in方式 (适应于数据库2012以下的版本)

select top 3 * from ArtistModels where ArtistId not in (select top 15 ArtistId from ArtistModels)

个人使用过ROW_NUMBER加Top方式:

确定开始页码的下标以及分页大小

select top 50 * from (select row_number()over(order by id)rownumber,* from pagetest)a where rownumber>9900

使用场景

1 创建自定义字段类型使用方法:

如果不存在某自定义类型,就创建某自定义类型

/*
	描述:编码临时表
	
	由于编码过多时,使用f_split函数创建表很慢,
	所以由程序后台直接生成此临时表传入存储过程使用
*/
IF NOT EXISTS (SELECT TOP 1 1 FROM sys.types st JOIN sys.schemas ss 
ON st.schema_id = ss.schema_id WHERE st.name = N'mst' AND ss.name = N'dbo')
BEGIN
	CREATE TYPE TbType_mst_Code AS TABLE
	(
		code NVARCHAR(255)
    )
END

2 判断是否存储过程,存在则删除

IF EXISTS ( SELECT  TOP 1 1
            FROM    dbo.sysobjects
            WHERE   id = OBJECT_ID(N'[dbo].[msp_Total]')
                    AND OBJECTPROPERTY(id, N'IsProcedure') = 1 )
    DROP PROCEDURE [dbo].msp_InspecYearTotal;

3 用分隔符分割字符串的一部分

ALTER FUNCTION [dbo].[f_split]
(
	@SourceSql varchar(MAX),
	@StrSeprate varchar(10)
)
returns @temp TABLE(a varchar(MAX))
AS 
BEGIN
    DECLARE @i int
    SET @SourceSql=RTRIM(LTRIM(@SourceSql))
    SET @i=charindex(@StrSeprate,@SourceSql)
    WHILE @i>=1
	    BEGIN
	        INSERT @temp VALUES(LEFT(@SourceSql,@i-1))
	        SET @SourceSql=SUBSTRING(@SourceSql,@i+1,len(@SourceSql)-@i)
	        SET @i=charindex(@StrSeprate,@SourceSql)
	    END
    IF @SourceSql<>'' 
       INSERT @temp VALUES(@SourceSql)
    RETURN 
END

4 对ROW_NUMBER() OVER( PARTITION BY name ORDER BY name ASC )的使用

统计出不同ID下不同name的个数(name可能重复)

常规写法,两次分组,第一次分组,对id,name进行去重,第二次对不同ID分组,每一组统计出不同name的个数。

SELECT TS.id ,COUNT(name) count  FROM (
SELECT   id,name FROM     table a  
WHERE    GROUP BY id,name
)TS  GROUP BY id,name

第一次用PARTITION by 对name进行分组再排序, 第二次只取排序等于1的,就去重了,再分组统计所有不同name个数(错误)

错误原因:只对name分组了,要同时对name,id一起分组,才能找到不同id下不同name个数

SELECT  TS.id ,COUNT(id) count  FROM (
SELECT   ROW_NUMBER() OVER( PARTITION BY name ORDER BY name ASC )rn,a.id 
FROM    table a    
)TS WHERE TS.rn = 1 GROUP BY TS.id

PARTITION by  只适应于一次分组,统计数据,比如统计不同客户,订单个数,同一个订单订单号会重复,

如果一个订单只针对一个客户。这样写就不会错。针对多个客户就会错。

SELECT  customerid ,COUNT(orderid) qty FROM (
SELECT   ROW_NUMBER() OVER( PARTITION BY a.orderid ORDER BY orderid ASC )rn,a.customerid AS customerid FROM     table
)TS WHERE TS.rn = 1 GROUP BY customerid 

如果既要统计账户余额,又要统计订单个数。可以用union all, 最后 group by sum

SELECT customerid,SUM(balance) balance,SUM(qty) qty FROM ( SELECT  customerid ,balance,0 FROM customer
UNION ALL SELECT  customerid ,0,COUNT(orderid) qty FROM (
SELECT   ROW_NUMBER() OVER( PARTITION BY a.orderid ORDER BY orderid ASC )rn,a.customerid AS customerid FROM     table
)TS WHERE TS.rn = 1 GROUP BY customerid) GROUP BY customerid

4 动态分页,利用sp_executesql,CEILING,数据库row_numer从1开始排序

		  SET @sqlsearch = '
				SELECT  @rowcount = COUNT(1)
				FROM    ('+@sql+') g'
		  EXEC sp_executesql @sqlsearch,
					N'@rowcount INT OUT',@rowcount OUTPUT; 		  
		  IF @rowcount = 0 
		  RETURN
	      SELECT @pageCount = CEILING(1.0 * @rowcount / @pageSize)
		  SELECT @StartRecord = (@PageIndex-1) * @PageSize + 1 ,@EndRecord =  @PageSize * @PageIndex   
		  SET @sql=' select * from ( 
             Select *, ROW_NUMBER() OVER(Order by BtypeId ) AS RowId 
             from ('+@sql+') t5
                 ) as t6 WHERE RowId between '''+@StartRecord+''' and '''+@EndRecord+''''

错误记录:

1  EXEC sp_executesql @sqlsearch   @sqlsearch的类型为VARCHAR(8000)错误,修改为NVARCHAR(MAX)

2      EXEC(‘’+@a);  @a类型为int错误,转化为字符串,修改为     EXEC(''+CAST (@a AS VARCHAR(100))); 

 

5  DATENAME的应用: 查询当前日期当年数据 并按照月份分组

select * FROM    table 
WHERE   DATENAME(YEAR, AddDate) = DATENAME(YEAR, @year)
        AND BillDate <= @year and a.Audited=1
GROUP BY DATENAME(MONTH, AddDate)
ORDER BY DATENAME(MONTH, AddDate);

6 通过存储过程名字查询所有参数

  • 通过sys.objects的name查出存储过程,
  • 通过all_parameters和object_id联查,查询出参数名
  • 通过sys.types和user_type_id联查,查询类型
SELECT  param.name AS ParamName ,usrt.name AS [DataType] 
        FROM    sys.objects AS sp
                LEFT OUTER JOIN sys.all_parameters AS param ON param.object_id = sp.object_id
                LEFT OUTER JOIN sys.types AS usrt ON usrt.user_type_id = param.user_type_id              
        WHERE   sp.type = 'P'
             --  AND sp.name = 'CheckExpression'

参考:

https://docs.microsoft.com

系统表:https://www.cnblogs.com/atree/p/SQL-Server-sysobjects.html

OBJECT_ID: https://www.cnblogs.com/AngelLee2009/p/3342730.html

partition by 开窗语句总结:https://www.lanhusoft.com/Article/170.html

分页:https://www.cnblogs.com/fengxiaojiu/p/7994124.html

动态SQL执行:https://www.cnblogs.com/railgunman/p/5770456.html

一、首先你要确认你的鉴别模式: WIN NT鉴别模式呢还是混合模式,其中混合模式包括WIN NT鉴别模式和SQL SERVER 鉴别模式 实施鉴别模式的步骤 1、核实采用了可信连接 2、设置鉴别模式 3、关闭和重启MSSQLServer服务程序 4、创建WIN NT分组和用户 5、授权WIN NT分组和用户可存取SQL Server 6、为用非可信任连接的用户创建SQL Server登录帐号 二、为用户和角色分配登录帐号 三、给角色分配登录权 四、为用户和角色分配许可权限 在改进SQL Server 7.0系列所实现的安全机制的过程中,Microsoft建立了一种既灵活又强大的安全管理 机制,它能够对用户访问SQL Server服务器系统和数据库的安全进行全面地管理。按照本文介绍的步骤,你 可以为SQL Server 7.0(或2000)构造出一个灵活的、可管理的安全策略,而且它的安全性经得起考验。 一、验证方法选择 本文对验证(authentication)和授权(authorization)这两个概念作不同的解释。验证是指检验用户 的身份标识;授权是指允许用户做些什么。在本文的讨论中,验证过程在用户登录SQL Server的时候出现, 授权过程在用户试图访问数据或执行命令的时候出现。 构造安全策略的第一个步骤是确定SQL Server用哪种方式验证用户。SQL Server的验证是把一组帐户、密 码Master数据库Sysxlogins表中的一个清单进行匹配。Windows NT/2000的验证是请求域控制器检查用户身 份的合法性。一般地,如果服务器可以访问域控制器,我们应该使用Windows NT/2000验证。域控制器可以是 Win2K服务器,也可以是NT服务器。无论在哪种情况下,SQL Server都接收到一个访问标记(Access Token)。 访问标记是在验证过程中构造出来的一个特殊列表,其中包含了用户的SID(安全标识号)以及一系列用户所 在组的SID。正如本文后面所介绍的,SQL Server以这些SID为基础授予访问权限。注意,操作系统如何构造访 问标记并不重要,SQL Server只使用访问标记中的SID。也就是说,不论你使用SQL Server 2000、SQL Server 7.0、Win2K还是NT进行验证都无关紧要,结果都一样。 如果使用SQL Server验证的登录,它最大的好处是很容易通过Enterprise Manager实现,最大的缺点在于 SQL Server验证的登录只对特定的服务器有效,也就是说,在一个多服务器的环境中管理比较困难。使用SQL Server进行验证的第二个重要的缺点是,对于每一个数据库,我们必须分别地为它管理权限。如果某个用户 对两个数据库有相同的权限要求,我们必须手工设置两个数据库的权限,或者编写脚本设置权限。如果用户数 量较少,比如25个以下,而且这些用户的权限变化不是很频繁,SQL Server验证的登录或许适用。但是,在几 乎所有的其他情况下(有一些例外情况,例如直接管理安全问题的应用),这种登录方式的管理负担将超过它 的优点。 二、Web环境中的验证 即使最好的安全策略也常常在一种情形前屈服,这种情形就是在Web应用中使用SQL Server的数据。在这 种情形下,进行验证的典型方法是把一组SQL Server登录名称和密码嵌入到Web服务器上运行的程序,比如 ASP页面或者CGI脚本;然后,由Web服务器负责验证用户,应用程序则使用它自己的登录帐户(或者是系统管 理员sa帐户,或者为了方便起见,使用Sysadmin服务器角色中的登录帐户)为用户访问数据。 这种安排有几个缺点,其中最重要的包括:它不具备对用户在服务器上的活动进行审核的能力,完全依 赖于Web应用程序实现用户验证,当SQL Server需要限定用户权限时不同的用户之间不易区别。如果你使用的 是IIS 5.0或者IIS 4.0,你可以用四种方法验证用户。第一种方法是为每一个网站和每一个虚拟目录创建一 个匿名用户的NT帐户。此后,所有应用程序登录SQL Server时都使用该安全环境。我们可以通过授予NT匿名 帐户合适的权限,改进审核和验证功能。 第二种方法是让所有网站使用Basic验证。此时,只有当用户在对话框中输入了合法的帐户和密码,IIS 才会允许他们访问页面。IIS依靠一个NT安全数据库实现登录身份验证,NT安全数据库既可以在本地服务器 上,也可以在域控制器上。当用户运行一个访问SQL Server数据库的程序或者脚本时,IIS把用户为了浏览 页面而提供的身份信息发送给服务器。如果你使用这种方法,应该记住:在通常情况下,浏览器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值