我必须将数据插入表中,但仅限于它尚不存在.
我使用以下方法检查现有行:
IF EXISTS (SELECT 'X' FROM Table1 where id = @id)
Run Code Online (Sandbox Code Playgroud)
是否会使用'X'提高性能而不是使用列名?
我正在浏览我们的代码库并看到很多像这样的测试:
declare @row_id int = ...
declare @row_attribute string
select
@row_attribute = ROW_ATTRIBUTE
from
SOME_TABLE
where
ROW_ID = @row_id
if @row_attribute is null
begin
... handle not existing condition
end
Run Code Online (Sandbox Code Playgroud)
这是问题,是否可以将if语句中的条件替换为:
if @@rowcount = 0
begin
... handle not existing condition
end
Run Code Online (Sandbox Code Playgroud)
我知道exist函数,但这里的目标是获取行的一些属性并同时检查它的存在.
我将 Entity Framework Core 3.1.8 与 SQL Server 2016 结合使用。
考虑以下示例(为了清晰起见,进行了简化):
数据库表定义如下:
CREATE TABLE [dbo].[Product]
(
[Id] INT IDENTITY(1,1) NOT NULL ,
[ProductName] NVARCHAR(500) NOT NULL,
CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED (Id ASC) WITH (FILLFACTOR=80),
CONSTRAINT [UQ_ProductName] UNIQUE NONCLUSTERED (ProductName ASC) WITH (FILLFACTOR=80)
)
Run Code Online (Sandbox Code Playgroud)
以及以下 C# 程序:
using System;
using System.Linq;
using System.Reflection;
namespace CcTest
{
class Program
{
static int Main(string[] args)
{
Product product = null;
string newProductName = "Basketball";
using (CcTestContext context = new CcTestContext())
using (var …Run Code Online (Sandbox Code Playgroud) c# sql-server concurrency entity-framework entity-framework-core
简单问题在这里.
上下文:具有int主键的Transact-SQL表,以及也必须是unqiue的名称(即使它不是主键).让我们说:
TableID INT,
TableName NVARCHAR(50)
Run Code Online (Sandbox Code Playgroud)
我正在通过存储过程为此功能添加新行(因此,使用参数指定TableName).
问题:验证表中是否已存在所提供的TableName参数的最佳/最简单方法是什么?如果是这种情况,则阻止添加新行?
可以在我的AddNewRow存储过程中直接执行此操作吗?
我的案例场景将参数传递给一个过程,该过程仅执行插入操作。但两个线程可能会尝试传递相同的值。
如何处理这种情况而不引发异常并使用最少的锁?
我的性能要求是每秒至少 10k 插入。
编辑:列是唯一的。时间戳在插入之前可能会被更改(调整)。
t-sql sql-server nonblocking transaction-isolation sqlperformance
我有一个C#控制台应用程序,它使用存储过程将行插入SQL Server数据库.目前,数据库有大约1米的行,但ID列的最大长度为26米!
在最后一次成功插入时,ID从16米到26米.该应用程序并行运行多个线程,因此有可能尝试同时插入两个东西.
除了事务回滚之外还有什么可以导致标识列在不添加行的情况下递增吗?
似乎不太可能有两千个线程试图同时写一个冲突的行.
我正在使用一个临时表变量,它通过将XML传递到存储过程来填充:
-- insert data if it doesn-t already exist
insert into DataStore (DataText, DataSourceID)
select distinct td.dataText, td.dataSource
from @tempData td
where not exists ( select 'x'
from DataStore ds
where ds.DataText = td.dataText );
Run Code Online (Sandbox Code Playgroud) insert into Attributes (Id, Disabled, AttributeValue)
values (@id, @disabled, @attr_value)
if not exists
(
select * from Attributes
where
Id = @id
)
Run Code Online (Sandbox Code Playgroud)
我也检查了这些问题.但是,如果不存在,它似乎没有插入使用的查询. 只有插入行,如果它不是已经存在和 SQL条件插入如果行不存在
如果我的数据库中不存在一个值,我想将数据插入到我的数据库中.
我有这个代码:
try
{
SQLConnection.Open();
string sql = "INSERT INTO shop (title, price, information) values (@chp1, @chp2,@chp3)";
SqlCommand cmd = new SqlCommand(sql, SQLConnection);
cmd.Parameters.AddWithValue("@chp1", title);
cmd.Parameters.AddWithValue("@chp2", price);
cmd.Parameters.AddWithValue("@chp3", information);
cmd.ExecuteNonQuery();
}
Run Code Online (Sandbox Code Playgroud)
我尝试在我的数据库中插入,如果我的数据库中不存在值"title".
在stackoverflow中,我已经创建了这个答案IF EXISTS,但我没有看到如何使用它...
在此先感谢您的回答:)
写作更好:
IF EXISTS (SELECT ...) OR EXISTS (SELECT ...)
BEGIN
INSERT INTO myTable
VALUES ('myValue1', 'myValue1')
END
Run Code Online (Sandbox Code Playgroud)
或者写:
INSERT INTO myTable
SELECT 'myValue1', 'myValue1'
WHERE EXISTS (SELECT ...) OR EXISTS (SELECT ...)
Run Code Online (Sandbox Code Playgroud)
?
我的意思是在性能和可读性方面更好.
Pileggi
我一直在寻找类似于此问题的问题,我现在还没有找到任何东西,所以如果以前曾经问过这个问题,那至少可以作为那些对正确命名法无知的人的指针.
INSERT INTO基于唯一键,如果一行尚不存在,我想要一个表.它确实存在,然后我想获得该行的主键ID.
想象一下一个包含电子邮件地址的表:
EmailAddressId(PK) | EmailAddress(UK)
Run Code Online (Sandbox Code Playgroud)
我想在INSERT该表中添加一个新的电子邮件地址,但是有一个独特的约束条件EmailAddress.因此,如果新的电子邮件地址与现有电子邮件地址相同,INSERT则将失败.在那种情况下,我想EmailAddressId从数据库中选择现有的EmailAddress.
我想在最少的操作中执行此操作,假设碰撞将是罕见的情况.
因此,我TRY...CATCH在存储过程中设置了一个块,如下所示:
ALTER PROCEDURE [dbo].[EmailAddressWrite]
@EmailAddress nvarchar[256]
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
DECLARE @EmailAddressId INT
BEGIN TRY
INSERT INTO EmailAddress VALUES (@EmailAddress)
SET @EmailAddressId = (SELECT SCOPE_IDENTITY())
END TRY
BEGIN CATCH
SET @EmailAddressId = (SELECT EmailAddressId FROM EmailAddress WHERE EmailAddress = @EmailAddress)
END CATCH
--Do some more stuff with the Id now.
COMMIT TRANSACTION
RETURN @EmailAddressId
END
Run Code Online (Sandbox Code Playgroud)
上面的代码起作用,并产生所需的结果,但互联网让我觉得 …
我有一个DB表,其字段必须是唯一的.假设该表称为"Table1",唯一字段称为"Field1".
我计划通过执行SELECT来查看是否存在任何Table1记录,其中Field1 = @ valueForField1,并且只有在没有这样的记录存在时才更新或插入.
问题是,我怎么知道这里没有竞争条件?如果两个用户都在写入Table1的表单上单击"保存"(几乎完全相同的时间),并且它们具有相同的Field1值,则不可能发生以下情况吗?
User1进行SQL调用,执行select操作并确定Field1 = @ valueForField1中没有现有记录.User1的进程被User2的进程抢占,该进程也找不到Field1 = @ valueForField1的记录,并执行插入.允许User1的进程再次运行,并在Field1 = @ valueForField1中插入第二条记录,违反了Field1唯一的要求.
我怎么能阻止这个?我被告知交易是原子的,但为什么我们也需要表锁?我之前从未使用过锁,我不知道在这种情况下是否需要锁.如果进程尝试写入锁定表会发生什么?它会阻止并重试吗?
我正在使用MS SQL 2008R2.
我有一个表"INSERTIF",看起来像这样 -
id value
S1 s1rocks
S2 s2rocks
S3 s3rocks
Run Code Online (Sandbox Code Playgroud)
在将一行插入此表之前,我想检查给定的ID是否存在.如果它不存在,则插入.否则,只需更新值即可.我想以线程安全的方式做到这一点.你能告诉我我的代码是否正确吗?我尝试了它,它的工作原理.但是,我想确保我没有遗漏任何性能问题.
编辑1-我想使用此代码一次插入数百万行.每个insert语句都包含在我显示的代码中.
编辑2 -我不想使用我的代码的UPDATE部分,只插入就足够了.
我不想使用MERGE,因为它只适用于SQL Server 2008及更高版本
谢谢.
代码 -
-- no check insert
INSERT INTO INSERTIF(ID,VALUE)
VALUES('S1', 's1doesNOTrock')
--insert with checking
begin tran /* default read committed isolation level is fine */
if not exists
(select * from INSERTIF with (updlock, rowlock, holdlock)
where ID = 'S1')
BEGIN
INSERT INTO INSERTIF(ID,VALUE)
VALUES('S1', 's1doesNOTrock')
END
else
/* update */
UPDATE INSERTIF
SET VALUE = 's1doesNOTrock'
WHERE ID = …Run Code Online (Sandbox Code Playgroud) sql-server ×12
sql ×6
t-sql ×4
c# ×3
concurrency ×2
identity ×1
if-statement ×1
insert ×1
merge ×1
nonblocking ×1
where ×1