226 sql t-sql sql-server sql-server-2008
我需要编写一个T-SQL存储过程来更新表中的行.如果该行不存在,请插入它.所有这些步骤都由事务包装.
这是一个预订系统,所以它必须是原子和可靠的.如果交易已提交且预订航班,则必须返回true.
我是T-SQL的新手,不知道如何使用@@rowcount.这是我到现在为止所写的.我在正确的道路上吗?我确信这对你来说很容易.
-- BEGIN TRANSACTION (HOW TO DO?)
UPDATE Bookings
SET TicketsBooked = TicketsBooked + @TicketsToBook
WHERE FlightId = @Id AND TicketsMax < (TicketsBooked + @TicketsToBook)
-- Here I need to insert only if the row doesn't exists.
-- If the row exists but the condition TicketsMax is violated, I must not insert
-- the row and return FALSE
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO Bookings ... (omitted)
END
-- END TRANSACTION (HOW TO DO?)
-- Return TRUE (How to do?)
Run Code Online (Sandbox Code Playgroud)
dan*_*die 154
看看MERGE命令.你可以做UPDATE,INSERT并DELETE在一个声明中.
这是一个使用的工作实现MERGE
- 它在进行更新之前检查航班是否已满,否则进行插入.
if exists(select 1 from INFORMATION_SCHEMA.TABLES T
where T.TABLE_NAME = 'Bookings')
begin
drop table Bookings
end
GO
create table Bookings(
FlightID int identity(1, 1) primary key,
TicketsMax int not null,
TicketsBooked int not null
)
GO
insert Bookings(TicketsMax, TicketsBooked) select 1, 0
insert Bookings(TicketsMax, TicketsBooked) select 2, 2
insert Bookings(TicketsMax, TicketsBooked) select 3, 1
GO
select * from Bookings
Run Code Online (Sandbox Code Playgroud)
然后 ...
declare @FlightID int = 1
declare @TicketsToBook int = 2
--; This should add a new record
merge Bookings as T
using (select @FlightID as FlightID, @TicketsToBook as TicketsToBook) as S
on T.FlightID = S.FlightID
and T.TicketsMax > (T.TicketsBooked + S.TicketsToBook)
when matched then
update set T.TicketsBooked = T.TicketsBooked + S.TicketsToBook
when not matched then
insert (TicketsMax, TicketsBooked)
values(S.TicketsToBook, S.TicketsToBook);
select * from Bookings
Run Code Online (Sandbox Code Playgroud)
Gre*_*mer 150
我假设每个航班都有一排?如果是这样:
IF EXISTS (SELECT * FROM Bookings WHERE FLightID = @Id)
BEGIN
--UPDATE HERE
END
ELSE
BEGIN
-- INSERT HERE
END
Run Code Online (Sandbox Code Playgroud)
我假设我所说的,因为你做事的方式可以超额预订航班,因为当最多10张票并且你预订20时它会插入一个新行.
Cas*_*cus 64
在测试行是否存在时,传递updlock,rowlock,holdlock提示.
begin tran /* default read committed isolation level is fine */
if not exists (select * from Table with (updlock, rowlock, holdlock) where ...)
/* insert */
else
/* update */
commit /* locks are released here */
Run Code Online (Sandbox Code Playgroud)
updlock提示会强制查询对该行进行更新锁定(如果已存在),从而阻止其他事务在您提交或回滚之前对其进行修改.
holdlock提示会强制查询执行范围锁定,从而阻止其他事务添加与筛选条件匹配的行,直到您提交或回滚为止.
行锁提示强制将粒度锁定到行级而不是默认页级,因此您的事务不会阻止尝试更新同一页中不相关行的其他事务(但要注意减少争用和增加之间的权衡)锁定开销 - 您应该避免在单个事务中占用大量行级锁定.
有关更多信息,请参见http://msdn.microsoft.com/en-us/library/ms187373.aspx.
请注意,锁被视为执行它们的语句 - 调用begin tran不会让你免受另一个事务的影响,在你到达它之前对某些事情进行锁定.您应该尝试通过尽快提交事务(获取较晚,尽早发布)来使SQL在最短的时间内保持锁定.
请注意,如果PK是bigint,则行级锁可能效果较差,因为SQL Server上的内部哈希值对于64位值是简并的(不同的键值可能会散列到相同的锁定ID).
Cem*_*Cem 37
我在写我的解决方案.我的方法不能代表'if'或'merge'.我的方法很简单.
INSERT INTO TableName (col1,col2)
SELECT @par1, @par2
WHERE NOT EXISTS (SELECT col1,col2 FROM TableName
WHERE col1=@par1 AND col2=@par2)
Run Code Online (Sandbox Code Playgroud)
例如:
INSERT INTO Members (username)
SELECT 'Cem'
WHERE NOT EXISTS (SELECT username FROM Members
WHERE username='Cem')
Run Code Online (Sandbox Code Playgroud)
说明:
(1)SELECT col1,col2 FROM TableName WHERE col1 = @ par1 AND col2 = @ par2它从TableName中选择搜索值
(2)SELECT @ par1,@ par2 WHERE NOT EXISTS如果不存在(1)子查询则需要
(3)插入TableName(2)步骤值
小智 6
我终于能够插入一行,条件是它不存在,使用以下模型:
INSERT INTO table ( column1, column2, column3 )
(
SELECT $column1, $column2, $column3
WHERE NOT EXISTS (
SELECT 1
FROM table
WHERE column1 = $column1
AND column2 = $column2
AND column3 = $column3
)
)
Run Code Online (Sandbox Code Playgroud)
我在以下位置找到的:
http://www.postgresql.org/message-id/87hdow4ld1.fsf@stark.xeocode.com
| 归档时间: |
|
| 查看次数: |
477981 次 |
| 最近记录: |