重新写了一个存储过程,从之前的700行缩短为200行。。。。
1.对于首先能结束存储过程的分支,要把判断写在前面,有goto或者return的语句就不需要写else了。
2.一次设置多个参数的值,不需要重复写set,直接select并以逗号相隔就可以。
3.判断之前的select是否有值,用@@ROWCOUNT = 0来判断,不用变量是否为空判断(@business_acctid)
如:--检查当前手机号是否注册服务
SELECT @business_acctid = acct_id
FROM mbphone
WHERE phone = @current_phone
AND country_code = @current_country_code
IF @@ROWCOUNT = 0 AND @@ERROR = 0
BEGIN
select @error = 101,@msg = 'Not find Acctid. Current phone is not register.',@call_active_count = 0;
GOTO result_end
END
4.对于测试环境和正式环境一些配置参数不同的问题,可以把配置参数传进来。配置参数的取值在Service端(存储过程调用端)通过webconfig进行配置。
如:@use_type INT
5.使用连接查询时,on后面的条件是连接两个表的关键条件。其他条件放在where后面
如:SELECT @access_number = speed_dial, @call_active_count = call_active_cnt
FROM speed_dial sp
INNER JOIN access_number ac ON ac.access_number = sp.speed_dial
WHERE sp.TYPE = @speed_call_type
AND sp.ACCTID = @business_acctid
6.某些分支,可以合并的尽量用“提取”的方法将条件精简。
如:AND ac.nation_code = @current_nation_code
AND ( ( @current_nation_code = 'CA'
AND ac.city = @city
)
OR ( @current_nation_code <> 'CA' )
)
7.随机排序可以直接加在最后。
如: ORDER BY NEWID() DESC
8.左联接 左表为主表,左表满足条件的行将列出,右表不能满足条件的用null填充。 因此只需要判断右表为null的行的左表的数据 就是没有使用过的。
如:--获取当前用户可选的AccessNumber(包含CA),随机获取
SELECT TOP 1 @access_number = access_number
FROM access_number ac
LEFT OUTER JOIN speed_dial sp ON ac.access_number = sp.speed_dial
AND sp.ACCTID = @business_acctid
AND sp.phone=@current_phone
WHERE ac.NUMBER_TYPE = @access_call_type
AND ac.CLIENT_TYPE = 'IPHONE'
AND ac.USE_TYPE = @use_type
AND ac.COUNTRY_CODE = @current_country_code
AND ac.nation_code = @current_nation_code
AND ( ( @current_nation_code = 'CA'
AND ac.city = @city
)
OR ( @current_nation_code <> 'CA' )
)
AND sp.speed_dial IS NULL
ORDER BY NEWID() DESC
9.多条件筛选可以考虑用多列排序解决。
如:ORDER BY call_active_cnt, LOADTIME ASC
10.transaction内只放insert,update,delete等语句,不放select语句。如果需要用到查询数据,可以在transaction外select到@变量中,判断是否需要更新时也可以设flag方式来判断。
如: IF @@ROWCOUNT = 1 AND @@ERROR = 0 -- 查找到了计数器为0的记录或者绑定时间最早的记录
BEGIN
SET @unbind_flag = 1 --需要进行解绑操作
END
ELSE --根据绑号规则,没有任何符合条件的号码提供绑定。
BEGIN
SELECT @error = 102,@call_active_count = 0,@msg = 'Bind Failure.Not Enough Access Number.'
GOTO result_end
END
BEGIN TRY
BEGIN TRANSACTION
IF @unbind_flag = 1
BEGIN
--Add a unbind log
INSERT INTO speed_dial_log ( acctid, phone, country_code, dnis_out, d_country_code,
speed_dial, s_country_code, operate, operator )
SELECT acctid, @current_phone, @current_country_code, dnis_out, d_country_code,
@log_access_number, s_country_code, 'Unbind', 'appAuto'
FROM mb_account_speed_dial
WHERE phone=@current_phone AND speed_dial = @log_access_number
--解绑查找到的号码
DELETE FROM mb_account_speed_dial
WHERE phone=@current_phone AND speed_dial = @log_access_number
END
------------------Begin Bind New Number---------------------
IF @access_number IS NULL
BEGIN
--获取需要绑定的速拨号码
SET @access_number = @log_access_number
END
INSERT INTO mb_account_speed_dial ( ACCTID, SPEED_DIAL, S_COUNTRY_CODE, TYPE, DNIS_OUT, D_COUNTRY_CODE, NAME,
LOADTIME, OP_ID, PHONE, P_COUNTRY_CODE )
VALUES ( @business_acctid, @access_number, @current_country_code, @speed_call_type, @out_phone,
@out_country_code, @name, GETDATE(), 'iPhone:' + RTRIM(LTRIM(STR(@business_acctid))), @current_phone,
@current_country_code )
--Add a bind log
INSERT INTO mb_account_speed_dial_log ( acctid, phone, country_code, dnis_out, d_country_code,
speed_dial, s_country_code, operate, operator )
VALUES ( @business_acctid, @current_phone, @current_country_code, @out_phone, @out_country_code,
@access_number, @current_country_code, 'BindNew', 'app' );
SELECT @call_active_count = 0,@error = 0,@msg = 'Bind New AccessNumber'
IF @unbind_flag = 1
BEGIN
SET @msg = 'Update AccessNumber'
END
------------------End Bind New Number---------------------
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT @error = ERROR_NUMBER(),@call_active_count = 0,@msg = ERROR_MESSAGE()
END CATCH
1.对于首先能结束存储过程的分支,要把判断写在前面,有goto或者return的语句就不需要写else了。
2.一次设置多个参数的值,不需要重复写set,直接select并以逗号相隔就可以。
3.判断之前的select是否有值,用@@ROWCOUNT = 0来判断,不用变量是否为空判断(@business_acctid)
如:--检查当前手机号是否注册服务
SELECT @business_acctid = acct_id
FROM mbphone
WHERE phone = @current_phone
AND country_code = @current_country_code
IF @@ROWCOUNT = 0 AND @@ERROR = 0
BEGIN
select @error = 101,@msg = 'Not find Acctid. Current phone is not register.',@call_active_count = 0;
GOTO result_end
END
4.对于测试环境和正式环境一些配置参数不同的问题,可以把配置参数传进来。配置参数的取值在Service端(存储过程调用端)通过webconfig进行配置。
如:@use_type INT
5.使用连接查询时,on后面的条件是连接两个表的关键条件。其他条件放在where后面
如:SELECT @access_number = speed_dial, @call_active_count = call_active_cnt
FROM speed_dial sp
INNER JOIN access_number ac ON ac.access_number = sp.speed_dial
WHERE sp.TYPE = @speed_call_type
AND sp.ACCTID = @business_acctid
6.某些分支,可以合并的尽量用“提取”的方法将条件精简。
如:AND ac.nation_code = @current_nation_code
AND ( ( @current_nation_code = 'CA'
AND ac.city = @city
)
OR ( @current_nation_code <> 'CA' )
)
7.随机排序可以直接加在最后。
如: ORDER BY NEWID() DESC
8.左联接 左表为主表,左表满足条件的行将列出,右表不能满足条件的用null填充。 因此只需要判断右表为null的行的左表的数据 就是没有使用过的。
如:--获取当前用户可选的AccessNumber(包含CA),随机获取
SELECT TOP 1 @access_number = access_number
FROM access_number ac
LEFT OUTER JOIN speed_dial sp ON ac.access_number = sp.speed_dial
AND sp.ACCTID = @business_acctid
AND sp.phone=@current_phone
WHERE ac.NUMBER_TYPE = @access_call_type
AND ac.CLIENT_TYPE = 'IPHONE'
AND ac.USE_TYPE = @use_type
AND ac.COUNTRY_CODE = @current_country_code
AND ac.nation_code = @current_nation_code
AND ( ( @current_nation_code = 'CA'
AND ac.city = @city
)
OR ( @current_nation_code <> 'CA' )
)
AND sp.speed_dial IS NULL
ORDER BY NEWID() DESC
9.多条件筛选可以考虑用多列排序解决。
如:ORDER BY call_active_cnt, LOADTIME ASC
10.transaction内只放insert,update,delete等语句,不放select语句。如果需要用到查询数据,可以在transaction外select到@变量中,判断是否需要更新时也可以设flag方式来判断。
如: IF @@ROWCOUNT = 1 AND @@ERROR = 0 -- 查找到了计数器为0的记录或者绑定时间最早的记录
BEGIN
SET @unbind_flag = 1 --需要进行解绑操作
END
ELSE --根据绑号规则,没有任何符合条件的号码提供绑定。
BEGIN
SELECT @error = 102,@call_active_count = 0,@msg = 'Bind Failure.Not Enough Access Number.'
GOTO result_end
END
BEGIN TRY
BEGIN TRANSACTION
IF @unbind_flag = 1
BEGIN
--Add a unbind log
INSERT INTO speed_dial_log ( acctid, phone, country_code, dnis_out, d_country_code,
speed_dial, s_country_code, operate, operator )
SELECT acctid, @current_phone, @current_country_code, dnis_out, d_country_code,
@log_access_number, s_country_code, 'Unbind', 'appAuto'
FROM mb_account_speed_dial
WHERE phone=@current_phone AND speed_dial = @log_access_number
--解绑查找到的号码
DELETE FROM mb_account_speed_dial
WHERE phone=@current_phone AND speed_dial = @log_access_number
END
------------------Begin Bind New Number---------------------
IF @access_number IS NULL
BEGIN
--获取需要绑定的速拨号码
SET @access_number = @log_access_number
END
INSERT INTO mb_account_speed_dial ( ACCTID, SPEED_DIAL, S_COUNTRY_CODE, TYPE, DNIS_OUT, D_COUNTRY_CODE, NAME,
LOADTIME, OP_ID, PHONE, P_COUNTRY_CODE )
VALUES ( @business_acctid, @access_number, @current_country_code, @speed_call_type, @out_phone,
@out_country_code, @name, GETDATE(), 'iPhone:' + RTRIM(LTRIM(STR(@business_acctid))), @current_phone,
@current_country_code )
--Add a bind log
INSERT INTO mb_account_speed_dial_log ( acctid, phone, country_code, dnis_out, d_country_code,
speed_dial, s_country_code, operate, operator )
VALUES ( @business_acctid, @current_phone, @current_country_code, @out_phone, @out_country_code,
@access_number, @current_country_code, 'BindNew', 'app' );
SELECT @call_active_count = 0,@error = 0,@msg = 'Bind New AccessNumber'
IF @unbind_flag = 1
BEGIN
SET @msg = 'Update AccessNumber'
END
------------------End Bind New Number---------------------
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT @error = ERROR_NUMBER(),@call_active_count = 0,@msg = ERROR_MESSAGE()
END CATCH
完整的存储过程代码:
-- =============================================
-- Author: DannyWang
-- Create date: 2012-08-01
-- Update date: 2013-02-01
-- Description: Dialer绑定速播回拨号码
-- Update: 重新整理SQL语句
-- =============================================
ALTER PROCEDURE bind_speed
@current_phone VARCHAR(32) ,
@current_country_code VARCHAR(10) ,
@current_nation_code VARCHAR(10) ,
@out_phone VARCHAR(64) ,
@out_country_code VARCHAR(10) ,
@name VARCHAR(64) ,
@city VARCHAR(32) ,
@operation VARCHAR(20) ,
@use_type INT
AS
DECLARE @error INT = 0
DECLARE @msg VARCHAR(100) = ''
DECLARE @business_acctid INT = 0
DECLARE @access_number VARCHAR(32)
DECLARE @call_active_count INT
DECLARE @access_call_type INT
DECLARE @speed_call_type INT
DECLARE @log_access_number VARCHAR(32)
DECLARE @unbind_flag INT= 0
IF @operation = 'speed_dial' --速直播
BEGIN
SELECT @access_call_type = 2, @speed_call_type = 0
END
ELSE
BEGIN
SELECT @access_call_type = 3, @speed_call_type = 1
END
--检查当前手机号是否注册服务
SELECT @business_acctid = acct_id
FROM phone_subscribe
WHERE phone = @current_phone
AND country_code = @current_country_code
IF @@ROWCOUNT = 0 AND @@ERROR = 0
BEGIN
select @error = 101,@msg = 'Not find Acctid. Current phone is not register.',@call_active_count = 0;
GOTO result_end
END
--手机号合法,检查之前是否有绑定关系
SELECT @access_number = speed_dial, @call_active_count = call_active_cnt
FROM speed_dial sp
INNER JOIN access_number ac ON ac.access_number = sp.speed_dial
WHERE sp.TYPE = @speed_call_type
AND sp.ACCTID = @business_acctid
AND sp.DNIS_OUT = @out_phone
AND sp.D_COUNTRY_CODE = @out_country_code
AND ( ( sp.PHONE = @current_phone
AND sp.P_COUNTRY_CODE = @current_country_code
)
OR ( RTRIM(LTRIM(sp.PHONE)) = ''
AND RTRIM(LTRIM(sp.P_COUNTRY_CODE)) = ''
)
)
AND ac.client_type = 'IPHONE'
IF @@ROWCOUNT > 0 AND @@ERROR = 0 --之前有绑定关系
BEGIN
SELECT @error = 0,@msg = 'This Number have binded.'
GOTO result_end;
END
--获取当前用户可选的AccessNumber(包含CA),随机获取
SELECT TOP 1 @access_number = access_number
FROM access_number ac
LEFT OUTER JOIN speed_dial sp ON ac.access_number = sp.speed_dial
AND sp.ACCTID = @business_acctid
AND sp.phone=@current_phone
WHERE ac.NUMBER_TYPE = @access_call_type
AND ac.CLIENT_TYPE = 'IPHONE'
AND ac.USE_TYPE = @use_type
AND ac.COUNTRY_CODE = @current_country_code
AND ac.nation_code = @current_nation_code
AND ( ( @current_nation_code = 'CA'
AND ac.city = @city
)
OR ( @current_nation_code <> 'CA' )
)
AND sp.speed_dial IS NULL
ORDER BY NEWID() DESC
IF @@ROWCOUNT = 0--没有满足条件的接入号码
BEGIN
-- 查找之前绑定关系中计数器为0或者绑定时间最早的记录
SELECT TOP 1 @log_access_number = speed_dial
FROM speed_dial sp
INNER JOIN access_number ac ON sp.speed_dial = ac.access_number
WHERE sp.type = @speed_call_type
AND sp.acctid = @business_acctid AND sp.phone = @current_phone
AND ac.nation_code = @current_nation_code
AND ( ( @current_nation_code = 'CA'
AND ac.city = @city
)
OR ( @current_nation_code <> 'CA' )
)
AND ac.client_type = 'IPHONE'
AND ac.USE_TYPE = @use_type
AND ac.NUMBER_TYPE = @access_call_type
ORDER BY call_active_cnt, LOADTIME ASC
IF @@ROWCOUNT = 1 AND @@ERROR = 0 -- 查找到了计数器为0的记录或者绑定时间最早的记录
BEGIN
SET @unbind_flag = 1 --需要进行解绑操作
END
ELSE --根据绑号规则,没有任何符合条件的号码提供绑定。
BEGIN
SELECT @error = 102,@call_active_count = 0,@msg = 'Bind Failure.Not Enough Access Number.'
GOTO result_end
END
END
BEGIN TRY
BEGIN TRANSACTION
IF @unbind_flag = 1
BEGIN
--Add a unbind log
INSERT INTO speed_dial_log ( acctid, phone, country_code, dnis_out, d_country_code,
speed_dial, s_country_code, operate, operator )
SELECT acctid, @current_phone, @current_country_code, dnis_out, d_country_code,
@log_access_number, s_country_code, 'Unbind', 'appAuto'
FROM speed_dial
WHERE phone=@current_phone AND speed_dial = @log_access_number
--解绑查找到的号码
DELETE FROM speed_dial
WHERE phone=@current_phone AND speed_dial = @log_access_number
END
------------------Begin Bind New Number---------------------
IF @access_number IS NULL
BEGIN
--获取需要绑定的速拨号码
SET @access_number = @log_access_number
END
INSERT INTO speed_dial ( ACCTID, SPEED_DIAL, S_COUNTRY_CODE, TYPE, DNIS_OUT, D_COUNTRY_CODE, NAME,
LOADTIME, OP_ID, PHONE, P_COUNTRY_CODE )
VALUES ( @business_acctid, @access_number, @current_country_code, @speed_call_type, @out_phone,
@out_country_code, @name, GETDATE(), 'iPhone:' + RTRIM(LTRIM(STR(@business_acctid))), @current_phone,
@current_country_code )
--Add a bind log
INSERT INTO speed_dial_log ( acctid, phone, country_code, dnis_out, d_country_code,
speed_dial, s_country_code, operate, operator )
VALUES ( @business_acctid, @current_phone, @current_country_code, @out_phone, @out_country_code,
@access_number, @current_country_code, 'BindNew', 'app' );
SELECT @call_active_count = 0,@error = 0,@msg = 'Bind New AccessNumber'
IF @unbind_flag = 1
BEGIN
SET @msg = 'Update AccessNumber'
END
------------------End Bind New Number---------------------
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT @error = ERROR_NUMBER(),@call_active_count = 0,@msg = ERROR_MESSAGE()
END CATCH
RESULT_END:
SELECT @error AS ERROR, @msg AS msg, @access_number AS access_number, @call_active_count AS call_active_count
GO