相关疑难解决方法(0)

检查是否存在行,否则插入

我需要编写一个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 …
Run Code Online (Sandbox Code Playgroud)

sql t-sql sql-server sql-server-2008

226
推荐指数
5
解决办法
48万
查看次数

SQL INSERT但避免重复

我想做一些快速插入,但避免重复到表中.为了论证,我们称之为MarketPrices,我一直在尝试两种方法,但不确定如何更快地进行基准测试.

INSERT INTO MarketPrices (SecurityCode, BuyPrice, SellPrice, IsMarketOpen)
SELECT @SecurityCode, @BuyPrice,  @SellPrice, @IsMarketOpen
EXCEPT
SELECT SecurityCode, BuyPrice, SellPrice, j.bool as IsActive FROM MarketPrices
CROSS JOIN (SELECT 0 as bool UNION SELECT 1 as bool ) as j
Run Code Online (Sandbox Code Playgroud)

要么

DECLARE @MktId int
SET @MktId = (SELECT SecurityId FROM MarketPrices 
              where SecurityCode = @SecurityCode 
              and BuyPrice=@BuyPrice 
              and SellPrice = @SellPrice)

IF (@MktId is NULL)  
BEGIN
    INSERT INTO MarketPrices (SecurityCode, BuyPrice, SellPrice, IsMarketOpen)
    VALUES
    (@SecurityCode,@BuyPrice, @SellPrice, @IsMarketOpen)
END
Run Code Online (Sandbox Code Playgroud)

假设这@whatever是存储过程中的输入参数.

我希望能够在BuyPrice或SellPrice或两者与之前的其他所有事件不同时为每个SecurityCode插入新记录.我不关心IsMarketOpen.

关于上述任何一种方法,有什么明显的愚蠢之处吗?一个比另一个快吗?

sql sql-server sql-server-2005

11
推荐指数
2
解决办法
2万
查看次数

如何通过选择插入时插入表格之前如何检查重复项

如何通过选择插入时插入表格之前如何检查重复项:

insert into table1
select col1, col2 
from table2
Run Code Online (Sandbox Code Playgroud)

我需要检查table1是否已经有一行table1.col1.value = table2.col1.value,如果是,则从插入中排除该行.

sql t-sql sql-server sql-server-2005 sql-server-2008

9
推荐指数
1
解决办法
3万
查看次数

在使用UNION时,SQL查询是否保证以原子方式执行?

我发出一个单独的SQL查询,包含使用UNION分组的多个SELECT:

SELECT *
FROM   employee 
       LEFT JOIN department 
          ON employee.DepartmentID = department.DepartmentID
UNION
SELECT *
FROM   employee
       RIGHT JOIN department
          ON employee.DepartmentID = department.DepartmentID;
Run Code Online (Sandbox Code Playgroud)

假设我在READ_COMMITTED事务隔离下执行此查询,两个SELECT语句是否保证以原子方式执行?或者我是否存在各个SELECT语句之间数据更改的风险?SQL规范是否讨论过这种事情?

澄清:当我说"原子"时,我不是指ACID中的"A".我的意思是我希望在查询完成之前对department和employee表进行读锁定.

sql transactions

8
推荐指数
1
解决办法
3171
查看次数

SQL Server:如果不存在则添加行,增加一列的值,原子

我有一个表,用于记录用户操作.每次执行操作时,值都需要增加.由于用户可以同时拥有多个会话,因此该过程需要是原子的,以避免多用户问题.

该表有3列:

  • ActionCodevarchar
  • UserIDint
  • Countint

我想通过ActionCodeUserID到将添加一个新行,如果一个已经不存在,并设置数量为1.如果该行确实存在一个功能,它只是一个增加数量. ActionCodeUserID组成此表的主要唯一索引.

如果我需要做的就是更新,我可以做这样简单的事情(因为UPDATE查询已经是原子的):

UPDATE (Table)
SET Count = Count + 1 
WHERE ActionCode = @ActionCode AND UserID = @UserID
Run Code Online (Sandbox Code Playgroud)

我是SQL新手中的原子事务.这个问题可能已在多个部分得到解答,但我找不到这些问题并将这些部分放在一个解决方案中.这也需要非常快,而不会变得复杂,因为这些操作可能经常发生.

编辑:对不起,这可能是MySQL的一个骗局如何在单个查询中执行if exists增量.我搜索了很多,但tsql在我的搜索中,一旦我改为sql相反,这是最好的结果.如果这是原子的,那不是很明显,但很确定它会是.我可能会投票删除这个作为欺骗,除非有人认为这个问题和答案可以增加一些新的价值.

sql sql-server atomic sql-server-2008

6
推荐指数
1
解决办法
4913
查看次数

防止多行的竞争条件

我已经阅读了很多关于防止竞争条件的内容,但通常在upsert场景中有一条记录.例如: SQL Server 2005中的Atomic UPSERT

我有不同的要求,它是为了防止多行的竞争条件.例如,假设我有以下表结构:

GiftCards:
  GiftCardId int primary key not null,
  OriginalAmount money not null

GiftCardTransactions:
  TransactionId int primary key not null,
  GiftCardId int (foreign key to GiftCards.GiftCardId),
  Amount money not null
Run Code Online (Sandbox Code Playgroud)

可能有多个进程插入GiftCardTransactions,我需要阻止插入,如果SUM(GiftCardTransactions.Amount) + insertingAmount将继续GiftCards.OriginalAmount.

我知道我可以使用TABLOCKXGiftCardTransactions,但很明显,对于很多的交易,这将是不可行的.另一种方法是添加一个GiftCards.RemainingAmount列,然后我只需要锁定一行(虽然可能会锁定升级),但不幸的是,这对我来说不是一个选项(这是最好的选择吗?).

可能答案只是插入,然后选择SUM(GiftCardTransactions.Amount),并在必要时回滚,而不是试图阻止插入.这是一个边缘情况,所以我不担心不必要地使用PK值等.

所以问题是,如果不修改表结构并使用事务,隔离级别和提示的任何组合,我如何通过最小量的锁定来实现这一点?

locking race-condition sql-server-2008

4
推荐指数
1
解决办法
5610
查看次数

为什么不允许MERGE语句的目标表启用规则?

我们有一个更新数据库的进程,它使用以下SQL

IF NOT EXISTS (SELECT * FROM Target_Table WHERE Target_Table_ID = ...)
BEGIN
    INSERT ...
END
ELSE
BEGIN
    UPDATE ...
END
Run Code Online (Sandbox Code Playgroud)

我想改变它以使用一个MERGE语句,以避免可能的竞争条件,其中单独评估IF和然后INSERTUPDATE语句.

但是,只要我执行查询,我就会收到错误:

MERGE语句的目标表'Target_Table'不能具有任何已启用的规则.找到规则'TargetTable_RULE'

我理解文档声明该表不能启用规则,虽然我在第一次阅读时错过了它,除了在执行之前禁用规则MERGE(我不认为这是一个可行的解决方案),似乎我坚持该IF NOT EXISTS解决方案.

该文件没有解释的是为什么目标表不允许有规则.在我的情况下,规则是> 0对值的简单检查.

有谁知道为什么在这种情况下不允许规则,是否有另一种方式以原子方式执行upsert?

编辑:正如Andriy M评论的问题SQL Server 2005中的Atomic UPSERT已经有大量关于原子upserts的信息,所以我不会在这里重复讨论.相反,我只想知道为什么MERGE语句无法在已定义规则的表上执行,是否有解决方法?

merge sql-server-2008

3
推荐指数
1
解决办法
2457
查看次数

如何在T-SQL中编写简单的插入或更新?

我有一个流程,我不想跟踪某些内容是创建还是更新.跟踪会很复杂.我想执行创建或更新.架构就像......

col1 varchar() (PK)
col2 varchar() (PK)
col3 varchar() (PK)
col4 varchar()
Run Code Online (Sandbox Code Playgroud)

我正在考虑做

TRY
{
    INSERT ...
}
CATCH(DuplicateKeyException)
{
    UPDATE ...
}
Run Code Online (Sandbox Code Playgroud)

你有什么建议?


我想确保我理解其他最高投票的答案.鉴于我的模式,UPDATE总是会发生(即使使用INSERT),但插入只发生在它不存在的地方?

 //UPSERT
INSERT INTO [table]
SELECT [col1] = @col1, [col2] = @col2, [col3] = @col3, [col4] = @col4
FROM [table]
WHERE NOT EXISTS (
    -- race condition risk here?
    SELECT  1 
    FROM [table] 
    WHERE [col1] = @col1 
        AND [col2] = @col2
        AND [col3] = @col3
)

UPDATE [table]
SET [col4] = @col4
WHERE [col1] = @col1 …
Run Code Online (Sandbox Code Playgroud)

sql sql-server-2000 upsert

2
推荐指数
1
解决办法
2959
查看次数

SQL - 仅在记录不存在时才插入INTO

我意识到在这个相同的主题上有很多回答SO问题,但我似乎无法使用任何这些信息来弄清楚我的查询有什么问题.

我正在尝试将记录插入到我的表中,只有具有相同记录database_ownerdatabase_name(我的两个列名称)的记录尚不存在.

我正在使用查询:

INSERT INTO users_databases (database_name, database_key, database_secret, database_owner) 
VALUES ('DB1', '263f690d-7ac3-49f2-aa3b-f5672e4639a2', '367123d8-e5a7-46a0-8101-21f39e6ac8d9', 'x@x.com') 
WHERE
   NOT EXISTS 
   (SELECT database_name FROM uses_databases WHERE database_name = 'DB1' AND database_owner = 'x@x.com');
Run Code Online (Sandbox Code Playgroud)

但是我收到了错误 Incorrect syntax near the keyword 'WHERE'.

我还应该指出运行查询

SELECT database_name 
FROM uses_databases 
WHERE database_name = 'DB1' AND database_owner = 'x@x.com' 
Run Code Online (Sandbox Code Playgroud)

确实会返回记录.

我哪里可能出错?从我在其他问题中看到的内容来看,这看起来是正确的.但显然不是.:-)任何建议都会非常有帮助.

c# sql sql-server

2
推荐指数
1
解决办法
4万
查看次数

在插入SQL Server中使用if条件

我的代码中有以下声明

INSERT INTO #TProductSales (ProductID, StockQTY, ETA1) 
VALUES (@ProductID, @StockQTY, @ETA1)
Run Code Online (Sandbox Code Playgroud)

我想做的事情如下:

IF @ProductID exists THEN 
   UPDATE #TProductSales 
ELSE 
   INSERT INTO #TProductSales
Run Code Online (Sandbox Code Playgroud)

有没有办法可以做到这一点?

t-sql sql-server upsert

-2
推荐指数
1
解决办法
184
查看次数