我需要编写一个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) 我想在我的表中插入数据,但只插入我的数据库中不存在的数据!
这是我的代码:
ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
(@_DE nvarchar(50),
@_ASSUNTO nvarchar(50),
@_DATA nvarchar(30) )
AS
BEGIN
INSERT INTO EmailsRecebidos (De, Assunto, Data)
VALUES (@_DE, @_ASSUNTO, @_DATA)
WHERE NOT EXISTS ( SELECT * FROM EmailsRecebidos
WHERE De = @_DE
AND Assunto = @_ASSUNTO
AND Data = @_DATA);
END
Run Code Online (Sandbox Code Playgroud)
错误是:
消息156,级别15,状态1,过程EmailsRecebidosInsert,第11行
关键字'WHERE'附近的语法不正确.
我想从数据库中获取一个对象(如果它已经存在)(基于提供的参数),或者如果不存在则创建它.
Django get_or_create(或来源)这样做.SQLAlchemy中是否有等效的快捷方式?
我目前正在明确地写出这样的:
def get_or_create_instrument(session, serial_number):
instrument = session.query(Instrument).filter_by(serial_number=serial_number).first()
if instrument:
return instrument
else:
instrument = Instrument(serial_number)
session.add(instrument)
return instrument
Run Code Online (Sandbox Code Playgroud) 我总是使用类似下面的东西来实现它:
INSERT INTO TheTable
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WHERE
PrimaryKey = @primaryKey)
Run Code Online (Sandbox Code Playgroud)
...但是一旦加载,就会发生主键违规.这是唯一插入此表的语句.那么这是否意味着上述陈述不是原子的?
问题是,这几乎不可能随意重建.
也许我可以将其更改为以下内容:
INSERT INTO TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
WHERE
PrimaryKey = @primaryKey)
Run Code Online (Sandbox Code Playgroud)
虽然,也许我使用错误的锁或使用过多的锁定或其他东西.
我在stackoverflow.com上看到了其他问题,其中答案是建议"IF(SELECT COUNT(*)... INSERT"等),但我总是在(可能是不正确的)假设单个SQL语句是原子的.
有没有人有任何想法?
我有一个包含多个SQL语句(INSERT,UPDATE和/或DELETES)的事务.执行时,我想忽略重复错误语句并继续下一个语句.这样做的最佳方法是什么?
我正在执行许多并发SQL INSERT语句,这些语句在UNIQUE KEY约束上发生冲突,即使我还在单个事务中检查给定键的现有记录.我正在寻找一种消除或最小化碰撞量的方法,而不会损害性能(太多).
背景:
我正在开发一个ASP.NET MVC4 WebApi项目,它接收大量的HTTP 记录POST请求INSERT.它每秒大约需要5K - 10K的请求.该项目的唯一责任是重复记录和汇总记录.这是非常重写; 它具有相对少量的读取请求; 所有这些都使用了一个Transaction IsolationLevel.ReadUncommitted.
数据库架构
这是DB表:
CREATE TABLE [MySchema].[Records] (
Id BIGINT IDENTITY NOT NULL,
RecordType TINYINT NOT NULL,
UserID BIGINT NOT NULL,
OtherID SMALLINT NULL,
TimestampUtc DATETIMEOFFSET NOT NULL,
CONSTRAINT [UQ_MySchemaRecords_UserIdRecordTypeOtherId] UNIQUE CLUSTERED (
[UserID], [RecordType], [OtherID]
),
CONSTRAINT [PK_MySchemaRecords_Id] PRIMARY KEY NONCLUSTERED (
[Id] ASC
)
)
Run Code Online (Sandbox Code Playgroud)
存储库代码
以下是Upsert导致异常的方法的代码:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using Dapper;
namespace MyProject.DataAccess …Run Code Online (Sandbox Code Playgroud) 我有一种方法可以在数据库中搜索实体并尝试创建它(如果不存在)。举个例子:
public async Country FindOrCreate(string name)
{
var country = _context.Countries.FirstOrDefault(p => p.Name == name);
if (country != null)
return country;
country = new Country
{
Name = name
};
_context.Countries.Add(country);
_context.SaveChanges();
return country;
}
Run Code Online (Sandbox Code Playgroud)
问题是:后台有多个任务FindOrCreate同时调用。我已通过创建唯一索引来防止插入重复项,但发生了以下情况,导致出现不需要的异常:
处理这些并发场景的适当方法是什么?我应该使用 C# 代码来处理锁吗?或者我应该设置交易吗?TIA
sql ×5
sql-server ×5
c# ×2
t-sql ×2
.net ×1
concurrency ×1
dapper ×1
database ×1
django ×1
locking ×1
python ×1
sqlalchemy ×1