局部变量
一、局部变量
局部变量一般出现在批处理、存储过程或触发器中。
●使用前必须用DECLARE语句定义。
●生存周期:仅生存于声明它的批处理、存储过程或触发器中,处
理结束后,其中的信息将丢失。
●必须提供变量名和数据类型
●变量名前必须有个@符。变量名最长不超过30个字符。
●如需要声明多个局部变量,可只用一个DECLARE语句。变量间
用“,”隔开。
●格式:DECLARE @变量名数据类型[,···]
二、为局部变量赋初值
1、用SELECT语句
SELECT @变量名=表达式[,···]
[ FROM <表名> ]
[ WHERE <条件表达式>]
●变量没赋值前为NULL值,如果在循环中使用它必须为其
赋值。
●一条SELECT语句只能返回一行,如果返回多行只将最后
一行的值赋给局部变量。
●由于使用不同的索引得到相同的结果,所以不好确定哪条
记录是最后一条记录,这时可使用ORDER BY子句。
●若包含了FROM子句,可用以下两种方法保证SELECT
语句返回一条记录。
1)在WHERE子句中使用关键码(主码)
2)SELECT 字段列表中使用一个集合函数。
例:赋值语句的各种表达形式
USE 教学库
GO
SELECT * FROM STU
DECLARE @PTR int , @sum int ,@xh char(4),@xm char(8), @TWO_XH CHAR(4),@TWO_XM CHAR(8)
---------------------------
SELECT @SUM=10
---------------------------
SELECT @XH=学号,@XM=姓名
FROM STU
-----------------------------
SELECT @TWO_XH=学号,@TWO_XM=姓名
FROM STU WHERE 姓名='林丽玲'
SELECT @PTR,@SUM,@XH,@XM,@TWO_XH,@TWO_XM 例2:使用集合函数为变量赋值。
USE 教学库
GO
SELECT * FROM GRE
DECLARE @CJ tinyint
-----------------------------
SELECT @CJ=MAX(成绩)
FROM gre
SELECT @CJ
GO
2、用SET语句为变量赋值
将先前使用DECLARE @local_variable 语句创建的指定局部变量设置为给定的值。
语法
SET @局部变量 = 表达式
| @游标变量 = @游标变量| 游标名
参数
@局部变量
是除text、ntext 或image 外的任何类型变量的名称。变量名必须以at 符(@) 开头。变量名必须符合标识符规则。表达式是任何有效的Microsoft? SQL S erver? 表达式。
游标变量:
是游标变量的名称。如果目标游标变量先前引用了一个不同的游标,则删除先前的引用。
游标名:
使用DECLARE CURSOR 语句声明的游标名。
指定SET 语句包含游标声明。
注释:
声明变量后,所有变量均初始化为NULL。使用SET 语句将一个不是NULL 的值赋给声明变量。SET 语句只能给一个变量赋值。当初始化多个变量时,为每个局部变量使用一个单独的SET 语句。变量只能用在表达式中,不能代替对象名或关键字。
权限
SET @局部变量权限默认授予所有用户。
示例
A. 输出使用SET 初始化的变量值
下例创建@myvar 变量,将一个字符串值放在变量中,并输出@myvar 变量的值。
DECLARE @myvar char(20)
SET @myvar = 'This is a test'
SELECT @myvar
GO
B. 在SELECT 语句中使用由SET 赋值的局部变量
下例创建一个名为@xb 的局部变量,并在SELECT 语句中使用该局部变量查找男生的信息。
USE 教学库
GO
DECLARE @xb char(2)
SET @xb = '男'
SELECT 系别,学号,姓名
FROM stu
WHERE 性别 = @xb
GO
C. 通过查询赋值
下例使用查询给变量赋值。
USE 教学库
GO
DECLARE @rows int
SET @rows = (SELECT COUNT(*) FROM STU)
PRINT '记录数为:'
PRINT @ROWS
D.对全局游标使用SET
下例创建一个局部变量,然后将游标变量设置为全局游标名。DECLARE my_cursor CURSOR GLOBAL FOR SELECT * FROM stu where 性别='男'
DECLARE @my_var CURSOR
SET @my_var = my_cursor
OPEN @my_var
FETCH NEXT FROM @my_var
--从服务器游标中检索特定的行
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM @my_var
END
DEALLOCATE my_cursor
注释:
?@@FETCH_STATUS
?返回被FETCH 语句执行的最后游标的状态,而不是任何当前被连接打开的游标的状态。
?返回值
?0 :FETCH 语句成功。
3、利用UPDATE为局部变量赋值。
例1 用UPDATE 语句为变量赋值。
USE 教学库
GO
SELECT * FROM STU
DECLARE @CSRQ tinyint
-----------------------------
UPDATE STU
SET @CSRQ=DAY(出生日期) +10
WHERE 学号='9801'
SELECT @CSRQ
GO
例2:使用带子查询的UPDATE语句为变量赋值。USE 教学库
GO
SELECT * FROM STU
DECLARE @CSRQ smalldatetime
-----------------------------
UPDATE STU
SET @CSRQ=(SELECT 出生日期 FROM STU WHERE 学号='9801')
SELECT @CSRQ
GO
注意:当子查询返回多个值时是不允许的。
4、输出局部变量值
1)SELECT语句:一句可输出多个变量
2)PRINT 语句:一句只能输出单个变量。
USE 教学库
GO
SELECT * FROM STU
DECLARE @PTR int , @sum int ,@xh char(4),@xm
char(8),
@TWO_XH CHAR(4),@TWO_XM CHAR(8) ---------------------------
SELECT @SUM=10
---------------------------
SELECT @XH=学号,@XM=姓名
FROM STU
-----------------------------
SELECT @TWO_XH=学号,@TWO_XM=姓名
FROM STU WHERE 姓名='林丽玲'
--SELECT
@PTR,@SUM,@XH,@XM,@TWO_XH,@TWO_XM
PRINT @PTR
PRINT @SUM
PRINT @XH
PRINT @XM
PRINT @TWO_XH
PRINT @TWO_XM
二、Transact-SQL程序设计
在Transact-SQL语言可以使用流程控制命令,与常见的程序设计语言类似,T-SQL也提供了顺序、判断循环结构,可以在存储过程、触发器中进行程序设计并把他们放置在服务器上运行。
一个服务器端程序通常由以下内容组成:
●批处理
●注释
●程序中使用的变量
●改变批处理中语句执行顺序的流控制语句
●错误和消息处理
●注释符
1、注释符
--
/* ··· */
2、块语句
从语法格式上讲,IF 、WHILE等语句体中,只允许包含一条语句,但这在实际程序设计中不能满足需要。这时就要用到BEGIN 和 END 语句。其中包括一系列的 Transact-SQL 语句,使得可以执行一组Transact-SQL 语句。在批处理时,整个语句块被视为一条语句。BEGIN 和 END 是控制流语言的关键字。
语法
BEGIN
{
sql命令行/程序块
}
END
说明:
虽然BEGIN - END可用在程序的任何地方,但最常用在WHILE或IF-ELSE组合中。
BEGIN - END可以嵌套。
3、判断语句IF-ELSE
语法
IF 条件表达式
sql命令行/程序块
[ ELSE
sql命令行/程序块 ]
如果不使用语句块BEGIN – END,IF或ELSE则只能执行一条命令。IF-ELSE语句可以进行嵌套。
例:带有子查询的IF语句的使用。
USE 教学库
GO
IF (SELECT AVG(成绩) FROM GRE WHERE 学号 = '9913' ) < 75 BEGIN
PRINT '平均成绩75以下的同学:'
PRINT ' '
SELECT 学号,课程编号,成绩
FROM GRE
WHERE 学号 = '9913'
END
ELSE
PRINT '该同学平均成绩都超过75分.'
4、IF EXISTS 语句
用于检查数据是否存在,而不考虑与之相匹配的总行数。
对于检查某个数据是否存在,使用IF-EXISTS 要比使用COUNT(*)>0的效率高,效果好。
语法
IF [NOT] EXISTS (SELECT 子查询)
sql命令行/程序块
[ ELSE
sql命令行/程序块 ]
说明:
只要找到第一个匹配的行,就停止执行SELECT子查询。
例:
USE 教学库
GO
IF EXISTS(SELECT STU.系别 , STU.学号 , STU.姓名 , dep.系名 FROM STU INNER JOIN DEP ON STU.系别 = dep.系别
WHERE 姓名 = '林丽玲' AND 系名='计算机' )
SELECT '林丽玲存在' --林丽玲在艺术设计系
ELSE
PRINT '林丽玲不存在.'
5、CASE语句
多分支语句,主要用于取代嵌套的IF语句。
CASE 具有两种格式:
简单CASE 函数将某个表达式与一组简单表达式进行比较以确定结果。
CASE 搜索函数计算一组布尔表达式以确定结果。两种格式都支持可选的 ELSE 参数。
语法
格式1:简单 CASE 语句:
CASE 算术表达式
WHEN 关系表达式THEN 结果表达式
WHEN 关系表达式THEN 结果表达式
···
[
ELSE 表达式
END
格式2:CASE 搜索函数:
CASE
WHEN 条件表达式 THEN 算术表达式
[ ...n ]
[
ELSE算术表达式
END
例:调整学生的成绩。凡低于70分增加10%,70~80分的增加5%,其他增加2%。
USE 教学库
GO
UPDATE GRE
SET 成绩=
CASE
WHEN 成绩<70 THEN 成绩*1.1
WHEN 成绩>=70 AND 成绩<80 THEN 成绩*1.08
WHEN 成绩>=80 AND 成绩<90 THEN 成绩*1.05
ELSE
成绩*1.2
END
--------------
SELECT * FROM GRE
6、循环语句 WHILE
语法
WHILE <条件表达式>
[ BREAK ]
[ CONTINUE ]
参数
条件表达式:
返回TRUE 或FALSE 的表达式。如果布尔表达式中含有SELECT 语句,必须用圆括号将SELECT 语句括起来。
sql命令行/程序块
Transact-SQL 语句或用语句块定义的语句分组。若要定义语句块,请使用控制流关键字BEGIN 和END。
BREAK
导致从最内层的WHILE 循环中退出。将执行出现在END 关键字后面的任何语句,END 关键字为循环结束标记。
CONTINUE
使WHILE 循环重新开始执行,忽略CONTINUE 关键字后的任何语句。
注释
如果嵌套了两个或多个WHILE 循环,内层的BREAK 将导致退出到下一个外层循环。
例:WHILE循环嵌套的使用
DECLARE @A int,@B int,@C int
SELECT @A=1,@B=1
WHILE @A<3
BEGIN
PRINT @A
WHILE @B<3
BEGIN
SELECT @C=100*@A+@B
PRINT @C
SELECT @B=@B+1
END
SELECT @A=@A+1
SELECT @B=1
END
7、GOTO(跳转)语句
将执行流变更到标签处。跳过 GOTO 之后的 Transact-SQL 语句,在标签处继续处理。GOTO 语句和标签可在过程、批处理或语句块中的任何位置使用。GOTO 语句可嵌套使用。
语法
定义标签:
label :
改变执行:
GOTO label
参数
label
若有 GOTO 语句指向此标签,则其为处理的起点。标签必须符合标识符规则。不论是否使用 GOTO 语句,标签均可作为注释方法使用。注释
●GOTO 可用在条件控制流语句、语句块或过程中,但不可跳转到批
处理之外的标签处。
●标签可是数字与字符的组合,但必须以”:”结尾。在GOTO 后
的标签后不用有“:”。
●使用GOTO语句要特别小心,特别是不要导致分析程序的混乱。例:分行打印字符‘1’、‘2’、‘3’、‘4’、‘5’
DECLARE @VAR CHAR(1)
SELECT @VAR='1'
LABEL_1:
PRINT @VAR
SELECT @VAR=@VAR+1
WHILE @VAR<6
GOTO LABEL_1
Verilog基本语法 【逻辑值】 逻辑0 表示低电平,GND 逻辑1 表示高电平,VCC 逻辑X 表示未知电平,可能是高电平,也可能是低电平 逻辑Z 表示高阻态,外部没有激励信号,是一个悬空状态 注:高阻态的实质:电路分析时高阻态可做开路理解。 可以把它看作输出(输入)电阻非常大,对下级电路无任何影响。 若为0、x、z则按照假处理;若为1,按真处理。 【进制】 二进制4'b0101 —4位二进制数0101 十进制数4’d2 —4位十进制数2 十六进制数4’ha —4位十六进制数a Verilog中若不指定位宽,默认32位;若不指定位宽不指定进制,默认32位宽的十进制数。 【标识符】 标识符可以是字母、数字、$和_(下划线)的组合,且开头必须是字母或下划线,区分大小写。不建议大小写混合使用。 【数据类型】 寄存器关键字reg,默认初始值位不定值X; reg[31:0] delay_cnt; //[31:0],指定寄存器位宽32位, reg key_reg; // 默认位宽为1. reg类型数据只能在always和initial语句中被赋值。 线网表示结构实体的物理连线,包括wire和tri类型 参数常量,用parameter定义。 parameter H_SYNC = 11'd41; 【运算符】 [条件操作符] ?: 例,a?b:c //如果a为真就选b,否则选择c。 result=(a>=b)?a:b; [逻辑运算符] !&& || [位运算符] ~ & | ^(按位异或) a&b; //自动将位宽小的数高位补零至较大数的位宽,然后按位与操作。[移位运算符] << >> 用0填补移出的空位。左移时位宽增加,右移位宽不变。 [位拼接运算符] {} 例,{a,b} //将a和b拼接起来,作为一个新信号,a为高位。 c={a,b[3:0]}; //a、b位宽均为8位,c为8+4=12位。
从Verilog 到VHDL(上)基本语法 16 六 从学校里开始,我所接触的就一直是VerilogHDL 而非更老牌的VHDL, 而且后续接触的项目中也多半是Verilog 的用户,坦白的讲,Verilog 的活力也确实更足一些,从 IEEE1800-2005 开始的SystemVerilog 的标准化,将 Verification 和Design 的一体化的尝试,我个人认为,是走在正确的道路上。 所以,我确实想不到,我竟然也要回头学起VHDL 来了,毕竟一些老牌公司,特别是欧洲的公司,往往因为历史原因,仍然在使用VHDL ,看来终究是绕不过去的了正如一个Design Verification 工程师在目前想完全的不和SpecmanE 打交道是很难的一样。 面记载的是两种语言学习过程中的一些体会,而且更多的是从语法角度出发,算是梳理一下思路吧,而且,以前从来 没有接触过VHDL ,当然会存在很多非常初级的东西。 而在本文之后,打算再写一篇简单阐述下结合Cadence 的IUS 工具,使用SystemVerilog 对VHDL 进行验证的基本方
法。 起手式从Verilog 撞进VHDL 的世界,有些东西要先搞清 楚,否则会一头雾水: 1. 大小写敏感:Verilog 是大小写敏感的,VHDL 则非; 2.注释:Verilog 的行注释为// ,块注释为/**/;VHDL 只 支持 行注释–;[1. 这个算是不方便的一个地方了,不过不 基本结构 论是在Vim 还是Emacs 当中,批量做行注释也很容易实现;] VHDL 被认为是要求更严格,更多讲究的语言,相比和 C 类 似的Verilog ,架构上更严谨一些: 1.基本结构:从上往下为 USE 定义区(调用库和包);Package 定义区(自定义程序包);Entity定义区(定义电路实体外观,I/O接口的规 格); [2. Entity 感觉像是 C 的头文件定义之类的东西,而在Verilog 当中,这些其实都是被整合在Module 里头一起完成 了。]Architecture 定义区(描述内部功能);[3. 同 上,相当于Verilog 的Module 内部实现。]Configuration 定义区(决定那个Architecture 被使用)[4. 这也许就是 之所以要分开 Arch 和Entity 的原因,类似的效果在Verilog 里实现,则
Verilog的词法约定 1Verilog是大小写相关的,其中的关键字全部为小写。 2空白符由空格、制表符、和换行符组成。 3单行注释以“//”开始,verilog将忽略此处到行尾的内容。多行注释以“/*” 开始,以“*/”结束。多行注释不允许嵌套 4操作符有三种:单目操作符、双目操作符和三目操作符。 5数字声明 Verilog中有两种数字生命:指明位数的数字和不指明位数的数字 指明位数的数字表示形式:
Verilog HDL语法基础(1) Verilog的词法约定 1Verilog是大小写相关的,其中的关键字全部为小写。 2空白符由空格、制表符、和换行符组成。 3单行注释以“//”开始,verilog将忽略此处到行尾的内容。多行注释以“/ *”开始,以“*/”结束。多行注释不允许嵌套 4操作符有三种:单目操作符、双目操作符和三目操作符。 5数字声明 Verilog中有两种数字生命:指明位数的数字和不指明位数的数字 指明位数的数字表示形式:
2.1 Verilog HDL的语言要素 Verilog HDL语法来源于C语言基本的语法,其基本此法约定与 C语言类似。 程序的语言要素称为语法,是由符号、数据类型、运算符和表达式构成的,其中符号包括空白符、注释符、和转义标示符、关键字、数值等。 2.1.1 空白符 空白符包括空格符(\b),制表符(\t)、换行符和换页符。空白符使代码看起来结构清晰,阅读起来更方便。在编译过程中,空白符被忽略。 2.1.2 注释符 Verilog HDL语言允许插入注释,标明程序代码功能、修改、版本等信息,以增强程序的可阅读性和帮助管理文档。 Verilog HDL有两种注释方式 1) 单行注释:单行注释以“ // ”开始,Verilog HDL 忽略从此处到行尾的内 容 2) 多行注释:多行注释以“ /* ”开始,到“ */ ”结束,Verilog 忽略 其中的注释内容
在Verilog HDL 中,标识符( Identifier )被用来命令信号名、模块名、参数名等。它可以使任意一组字母、数字、$符号和_符号的组合。应该注意的是,标识符的字符区分大小写,并且第一个字符必须是字母或者下划线 Verilog HDL规定了转义标识符(Escaped Identifie) 采用转义字符可以在一 条标识符中包含任何可打印的字符。转义标识符以“ ”(反斜线)符号开头,以 空白符结尾(空白可以是一个空格、一个制表符或者换行符) 2.1.4 关键字 Verilog HDL语言内部已经使用的词称为关键字或保留字,它是 Verilog HDL语言的内部专用词,是事先定义好的确认符,用来组织语言结构的。需要注意的是,在Verilog HDL中,保留字都是小写的。
第三章 Verilog HDL的基本语法 前言 Verilog HDL是一种用于数字逻辑电路设计的语言。用Verilog HDL描述的电路设计就是该电路的Verilog HDL模型。Verilog HDL既是一种行为描述的语言也是一种结构描述的语言。这也就是说,既可以用电路的功能描述也可以用元器件和它们之间的连接来建立所设计电路的Verilog HDL模型。Verilog模型可以是实际电路的不同级别的抽象。这些抽象的级别和它们对应的模型类型共有以下五种: ?系统级(system):用高级语言结构实现设计模块的外部性能的模型。 ?算法级(algorithm):用高级语言结构实现设计算法的模型。 ?RTL级(Register Transfer Level):描述数据在寄存器之间流动和如何处理这些数据的模型。 ?门级(gate-level):描述逻辑门以及逻辑门之间的连接的模型。 ?开关级(switch-level):描述器件中三极管和储存节点以及它们之间连接的模型。 一个复杂电路系统的完整Verilog HDL模型是由若干个Verilog HDL模块构成的,每一个模块又可以由若干个子模块构成。其中有些模块需要综合成具体电路,而有些模块只是与用户所设计的模块交互的现存电路或激励信号源。利用Verilog HDL语言结构所提供的这种功能就可以构造一个模块间的清晰层次结构来描述极其复杂的大型设计,并对所作设计的逻辑电路进行严格的验证。 Verilog HDL行为描述语言作为一种结构化和过程性的语言,其语法结构非常适合于算法级和RTL级的模型设计。这种行为描述语言具有以下功能: ?可描述顺序执行或并行执行的程序结构。 ?用延迟表达式或事件表达式来明确地控制过程的启动时间。 ?通过命名的事件来触发其它过程里的激活行为或停止行为。 ?提供了条件、if-else、case、循环程序结构。 ?提供了可带参数且非零延续时间的任务(task)程序结构。 ?提供了可定义新的操作符的函数结构(function)。 ?提供了用于建立表达式的算术运算符、逻辑运算符、位运算符。 ?Verilog HDL语言作为一种结构化的语言也非常适合于门级和开关级的模型设计。因其结构化的特点又使它具有以下功能: -提供了完整的一套组合型原语(primitive); -提供了双向通路和电阻器件的原语; -可建立MOS器件的电荷分享和电荷衰减动态模型。 Verilog HDL的构造性语句可以精确地建立信号的模型。这是因为在Verilog HDL中,提供了延迟和输出强度的原语来建立精确程度很高的信号模型。信号值可以有不同的的强 度,可以通过设定宽范围的模糊值来降低不确定条件的影响。 Verilog HDL作为一种高级的硬件描述编程语言,有着类似C语言的风格。其中有许多语句如:if语句、case语句等和C语言中的对应语句十分相似。如果读者已经掌握C语言编程的基础,那么学习Verilog HDL并不困难,我们只要对Verilog HDL某些语句的特殊方面着重理解,并加强上机练习就能很好地掌握它,利用它的强大功能来设计复杂的数字逻辑电路。下面我们将对Verilog HDL中的基本语法逐一加以介绍。 3.1.简单的Verilog HDL模块 3.1.1.简单的Verilog HDL程序介绍
Verilog语法总结 数电基础 能够存储1位二值信号的基本单元电路统称为触发器。 根据逻辑功能的不同特点,可以将数字电路分成两大类: 组合逻辑电路和时序逻辑电路。 组合逻辑电路中,任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关。 时序逻辑电路中,任一时刻的输出不仅取决于当时的输入信号,而且还取决于电路原来的状态。或者说还与以前的输入有关,因此时序逻辑必须具备记忆功能。 组合逻辑电路时序逻辑电路 逻辑值 逻辑0:表示低电平,也就对应我们电路GND; 逻辑1:表示高电平,也就是对应我们电路的 VCC; 逻辑X:表示未知,有可能是高电平,也有可能 是低电平; 逻辑Z:表示高阻态,外部没有激励信号,是一 个悬空状态。 数字进制格式 Verilog数字进制格式包括二进制、八进制、十进
制和十六进制。 一般常用的为二进制、十进制和十六进制。 二进制表示如下:4’b0101 表示4位二进制数字0101 十进制表示如下:4’d2 表示4位十进制数字2(二进制0010) 十六进制表示如下:4’ha 表示4位十六进制数字a(二进制1010) 16’b1001_1010_1010_1001 = 16’h9AA9 第一个表示用几个二进制位可以表示、’为语法、b为二进制,d为十进制,h为16进制,后面则表示要输出输入的字。(括号内为二进制表示,因为最终在计算机中都会变为二进制表示) 标识符 标识符可以是任意一组字母、数字、$符号和_(下划线)符号的组合; 但标识符的第一个字符必须是字母或者下划线; 标识符是区分大小写的; 数据类型 在Verilog 语言中,主要有三大类数据类型:寄存器数据类型、线网数据类型和参数数据类型。 寄存器类型: 寄存器表示一个抽象的数据存储单元,通过赋值语句可以改变寄存器储存的值寄存器数据类型的关键字是reg,reg 类型数据的默认初始值为不定值x reg类型的数据只能在always 语句和initial 语句中被赋值。 如果该过程语句描述的是时序逻辑,即always语句带有时钟信号,则该寄存器变量对应为触发器; 如果该过程语句描述的是组合逻辑,即always语句不带有时钟信号,则该寄存器变量对应为硬件连线; 线网类型: 线网数据类型表示结构实体(例如门)之间的物理连线。线网类型的变量