CREATE PROCEDURE OrderProcessing
@OrderID INT
AS
BEGIN
-- 判断订单是否存在
IF NOT EXISTS (SELECT * FROM Orders WHERE OrderID = @OrderID)
BEGIN
RAISERROR ('Invalid order ID', 16, 1)
RETURN
END
-- 获取订单状态
DECLARE @Status VARCHAR(20)
SELECT @Status = Status FROM Orders WHERE OrderID = @OrderID
-- 根据订单状态执行不同的操作
IF @Status = 'New'
BEGIN
UPDATE Orders SET Status = 'Processing' WHERE OrderID = @OrderID
EXEC StartOrderProcessing @OrderID
END
ELSE IF @Status = 'Processing'
BEGIN
DECLARE @Attempts INT
SET @Attempts = 0
WHILE @Attempts < 3
BEGIN
-- 模拟订单处理过程中断
WAITFOR DELAY '00:00:10'
-- 检查订单处理是否完成
IF EXISTS (SELECT * FROM OrderProcessingLog WHERE OrderID = @OrderID AND CompleteTime IS NOT NULL)
BEGIN
UPDATE Orders SET Status = 'Completed' WHERE OrderID = @OrderID
EXEC NotifyCustomer @OrderID
BREAK
END
ELSE
BEGIN
SET @Attempts = @Attempts + 1
END
END
IF @Attempts = 3
BEGIN
-- 处理失败,通知客服人员
EXEC NotifySupport @OrderID
END
END
ELSE IF @Status = 'Completed'
BEGIN
RAISERROR ('This order has already been completed', 16, 1)
RETURN
END
END
该存储过程的逻辑如下:
首先判断指定的订单是否存在。如果不存在,抛出一个异常并退出存储过程。
获取订单的状态,并根据不同的状态执行不同的操作。
如果订单状态是 New,则将其状态更新为 Processing 并调用名为 StartOrderProcessing 的存储过程,开始处理订单。
如果订单状态是 Processing,则重复执行以下步骤,直到订单处理完成或尝试次数达到 3 次:
等待 10 秒钟(模拟订单处理过程中断)。
检查订单处理是否已经完成。
如果处理完成,则将订单状态更新为 Completed、调用名为 NotifyCustomer 的存储过程通知客户,并退出循环。
如果未完成,则增加尝试次数。
如果尝试次数达到 3 次,则认为处理失败,调用名为 NotifySupport 的存储过程通知客服人员。
如果订单状态是 Completed,则抛出一个异常并退出存储过程。
该存储过程涉及到许多高级语法和逻辑,包括条件判断、循环、异常处理等。通过这个示例,您可以更好地理解 SQL Server 存储过程的复杂性,并了解如何使用它们来管理复杂的业务逻辑。
CalculateEmployeeSalary,它接受三个输入参数 @EmployeeID、@StartDate 和 @EndDate,并计算指定员工在指定时间段内的薪水总额,并将结果作为输出参数返回。该存储过程的逻辑如下:
CREATE PROCEDURE CalculateEmployeeSalary
@EmployeeID INT,
@StartDate DATE,
@EndDate DATE,
@TotalSalary MONEY OUTPUT
AS
BEGIN
DECLARE @Salary MONEY
-- 计算薪水总额
SELECT @Salary = SUM(Salary)
FROM SalaryHistory
WHERE EmployeeID = @EmployeeID
AND StartDate >= @StartDate
AND EndDate <= @EndDate
-- 设置输出参数
SET @TotalSalary = @Salary
END
举例
CREATE PROCEDURE [dbo].[proc_AddOrUpdate_CustomParts]
@id BIGINT,
@PartNumber VARCHAR(50),
@BPartNumber VARCHAR(50),
@GroupName VARCHAR(50),
@VendorFill VARCHAR(50),
@InternalVersion VARCHAR(50),
@CustomerInternalEngineering VARCHAR(50),
@UserName VARCHAR(50),
@ReturnCode INT OUTPUT,
@ReturnMSG VARCHAR(200) OUTPUT
AS
BEGIN
DECLARE @NewID INT, @count INT;
-- 初始化返回值
SELECT @ReturnCode = -1, @ReturnMSG = '失败';
-- 开始事务处理
BEGIN TRAN gusn;
IF (@id > 0)
BEGIN
-- 更新现有客制化零件信息
UPDATE Custom_Parts SET VendorFill = @VendorFill, InternalVersion = @InternalVersion, CustomerInternalEngineering = @CustomerInternalEngineering, WhoUpdate = @UserName, UpdateDate = GETDATE()
WHERE id = @id;
-- 检查是否更新成功
IF @@ERROR <> 0
BEGIN
-- 如果发生错误,回滚事务并退出
GOTO ErrTransHandle;
END
-- 将旧记录插入到历史表中进行备份
INSERT INTO Custom_Parts_History SELECT * FROM Custom_Parts WHERE id = @id;
IF @@ERROR <> 0
BEGIN
GOTO ErrTransHandle;
END
-- 更新 Custom_Parts_Detail 表中对应的记录
UPDATE Custom_Parts_Detail SET id = @id WHERE PartNumber = @PartNumber AND BPartNumber = @BPartNumber AND GroupName = @GroupName;
IF @@ERROR <> 0
BEGIN
GOTO ErrTransHandle;
END
-- 将旧记录插入到历史表中进行备份
INSERT INTO Custom_Parts_Detail_History SELECT * FROM Custom_Parts_Detail WHERE id = @id;
IF @@ERROR <> 0
BEGIN
GOTO ErrTransHandle;
END
END
ELSE
BEGIN
-- 检查是否已经存在相同的零件分组
SELECT @count = COUNT(*) FROM Custom_Parts WHERE PartNumber = @PartNumber AND BPartNumber = @BPartNumber AND GroupName = @GroupName;
IF (@count > 0)
BEGIN
-- 如果零件分组已存在,设置返回消息并退出
SELECT @ReturnMSG = '已维护';
GOTO ErrTransHandle;
END
-- 添加新的客制化零件信息
INSERT INTO Custom_Parts (PartNumber, BPartNumber, GroupName, VendorFill, InternalVersion, CustomerInternalEngineering, WhoRec) VALUES
(@PartNumber, @BPartNumber, @GroupName, @VendorFill, @InternalVersion, @CustomerInternalEngineering, @UserName);
IF @@ERROR <> 0
BEGIN
GOTO ErrTransHandle;
END
SET @NewID = @@IDENTITY;
-- 将新记录插入到历史表中进行备份
INSERT INTO Custom_Parts_History SELECT * FROM Custom_Parts WHERE id = @NewID;
IF @@ERROR <> 0
BEGIN
GOTO ErrTransHandle;
END
-- 更新 Custom_Parts_Detail 表中对应的记录
UPDATE Custom_Parts_Detail SET id = @NewID WHERE PartNumber = @PartNumber AND BPartNumber = @BPartNumber AND GroupName = @GroupName;
IF @@ERROR <> 0
BEGIN
GOTO ErrTransHandle;
END
-- 将新记录插入到历史表中进行备份
INSERT INTO Custom_Parts_Detail_History SELECT * FROM Custom_Parts_Detail WHERE id = @NewID;
IF @@ERROR <> 0
BEGIN
GOTO ErrTransHandle;
END
END
-- 设置返回值并提交事务
SELECT @ReturnCode = 0, @ReturnMSG = '成功';
COMMIT TRAN gusn;
RETURN @ReturnCode;
ErrHandle:
RETURN @ReturnCode;
ErrTransHandle:
-- 回滚事务并设置返回值
ROLLBACK TRAN gusn;
RETURN @ReturnCode;
END;
IF OBJECT_ID('dbo.MyStoredProcedure', 'P') IS NOT NULL
DROP PROCEDURE dbo.MyStoredProcedure
GO
CREATE PROCEDURE dbo.MyStoredProcedure
@inputString VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION
DECLARE @tempTable TABLE (id INT, name VARCHAR(50), age INT)
-- 将输入字符串拆分为临时表
INSERT INTO @tempTable
SELECT
CAST(LEFT(item, CHARINDEX(',', item) - 1) AS INT),
SUBSTRING(item, CHARINDEX(',', item) + 1, LEN(item)),
NULL
FROM
STRING_SPLIT(@inputString, ';')
-- 检查最后一条 SQL 语句是否有错误
IF @@ERROR != 0
GOTO ErrorHandler;
-- 根据姓名匹配更新年龄列
UPDATE
t
SET
t.age = c.age
FROM
@tempTable t
INNER JOIN
dbo.Customers c ON t.name = c.name
-- 检查最后一条 SQL 语句是否有错误
IF @@ERROR != 0
GOTO ErrorHandler;
-- 如果没有更新行,则引发错误
IF @@ROWCOUNT = 0
BEGIN
RAISERROR('没有更新行。', 16, 1)
GOTO ErrorHandler;
END
-- 将年龄转换为字符串,并使用 CASE WHEN 语句设置消息
DECLARE @ageMessage VARCHAR(100)
SET @ageMessage =
CASE
WHEN MAX(t.age) < 18 THEN '年轻人'
WHEN MAX(t.age) >= 18 AND MAX(t.age) <= 65 THEN '成年人'
ELSE '老年人'
END
-- 打印带有年龄类别的消息
PRINT '列表中最年长的人是:' + @ageMessage
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
-- 打印错误消息及其详细信息
PRINT '错误:' + ERROR_MESSAGE() + ',行:' + CAST(ERROR_LINE() AS VARCHAR(10))
-- 返回错误代码
RETURN @@ERROR;
END CATCH
-- 如果没有出现错误,则返回 0
RETURN 0;
ErrorHandler:
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
-- 返回错误代码
RETURN @@ERROR;
END
GO
EXEC dbo.MyStoredProcedure '1,John;2,Jane;3,Bob;'
在这个例子中,假设 Customers 表中有如下数据:
id name age
1 John 24
2 Jane 33
3 Alice 12
4 Bob 47
因此,存储过程将打印出以下消息:
The oldest person in the list is a(n) Adult
高级语法之发起http业务
IF CHARINDEX('{', @responseText) = 0
判断是否存在{
@access_token = JSON_VALUE(@JSON, '$.access_token');
从json字符串解析键access_token
,内容为{ "accesstoken":"xxxxxxxxxx"}
ALTER PROCEDURE [dbo].[SendMessageToWechat]
@corp_id varchar(50),
@secret varchar(50),
@touser varchar(50),
@agent_id varchar(50),
@content varchar(500),
@returnResult varchar(8000) output,
@returnCode int output,
@returnMsg varchar(8000) output
AS
BEGIN
DECLARE @Object INT;
DECLARE @Url VARCHAR(2000);
DECLARE @Result VARCHAR(MAX);
DECLARE @access_token VARCHAR(800);
declare @errmsg varchar(500);
DECLARE @POST VARCHAR(MAX);
SET @Url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=' + @corp_id + '&corpsecret=' + @secret;
DECLARE @return_value int,
@responseText varchar(8000),
@responseStatus varchar(800),
@responseCode varchar(800)
set @responseCode='900'
EXEC @return_value = [dbo].[SP_HTTPRequest]
@URI = @Url,
@methodName = N'get',
@responseText = @responseText OUTPUT,
@responseStatus = @responseStatus OUTPUT,
@responseCode = @responseCode OUTPUT
IF @responseCode<>'200'
BEGIN
set @returnResult=@responseText;
set @returnCode=CAST(@responseCode AS INT);
set @returnMsg='GetTokenFail,HttpResponseError StatusCode is'+@responseCode;
RETURN;
END
IF CHARINDEX('{', @responseText) = 0
BEGIN
set @returnResult=@responseText;
set @returnCode=800;
set @returnMsg='GetTokenFail,ParseJSONFormatError ,Content Format Error';
RETURN;
END
DECLARE @JSON NVARCHAR(MAX) = @responseText;
DECLARE @errcode INT = JSON_VALUE(@JSON, '$.errcode');
IF @errcode <> 0
BEGIN
set @returnResult=@responseText;
set @returnCode=800;
set @returnMsg='GetTokenFail,pusherrcode is '+@errcode;
RETURN;
END
set @access_token = JSON_VALUE(@JSON, '$.access_token');
SET @POST = '{
"touser": "' + @touser + '",
"agentid": ' + @agent_id + ',
"is_to_all": true,
"msgtype": "text",
"text": {
"content": "' + @content + '"
}
}';
SET @Url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token='+ @access_token;
EXEC @return_value = [dbo].[SP_HTTPRequest]
@URI = @Url,
@methodName = N'post',
@requestBody = @POST,
@responseText = @responseText OUTPUT,
@responseStatus = @responseStatus OUTPUT,
@responseCode = @responseCode OUTPUT
IF @responseCode<>'200'
BEGIN
set @returnResult=@responseText;
set @returnCode=CAST(@responseCode AS int);
set @returnMsg='SendFail,HttpResponseError StatusCode is'+@responseCode;
RETURN;
END
IF CHARINDEX('{', @responseText) = 0
BEGIN
set @returnResult=@responseText;
set @returnCode=800;
set @returnMsg='SendFail,ParseJSONFormatError ,Content Format Error';
RETURN;
END
set @JSON = @responseText;
--select JSON_VALUE(@JSON, '$.errcode')
set @errcode =CAST(JSON_VALUE(@JSON, '$.errcode') as int);
set @errmsg =JSON_VALUE(@JSON, '$.errmsg');
IF @errcode <> 0
BEGIN
set @returnResult=@responseText;
set @returnCode=800;
set @returnMsg='PushFail,Pusherrcode is '+cast(@errcode as varchar(100))+ ' '+@errmsg --+' token is '+@access_token;
RETURN;
END
set @returnResult=@responseText;
set @returnCode=200;
set @returnMsg='PushSuccess';
END
网友评论