Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

запрос sql: если есть изменить запись если нет то добавить запись [D7, MSSQL]


Страницы:   1 2

redlord ©   (2005-07-17 21:26:00) 

всем привет
народ помогите составить запрос sql к базе mssql
имеется таблица с тремя полями f1 f2 f3 записи в f1 уникальны
мне нужно добавлять строку тока в том случае если значение из добавляемой строки в поле f1 не совпадает ни с одним значение поля F1 уже имеющихся в таблице.а если совпадают то поменять у уже имеюжейся записи значение поля f2


redlord   (2005-07-18 23:51:00) [1]

очен жалко что позно зашол на ветку да и сечас уже поздно а завтра обязательно изучу все посты
спасибо всем откликнувшимся


Fay   (2005-07-18 11:46:00) [2]

Сам проверил - всё ОК.
Остаётся только тщательней следить за захватом ресурсов воизбежание deadlock-ов.


MOA   (2005-07-18 11:45:00) [3]

>evvcom ©   (18.07.05 11:38) [29]
>> WAITFOR DELAY '00:00:05'
>А это зачем?
А это чтобы наглядно проверить (чтобы кнопулю успеть нажать во втором сеансе), что транзакции отрабатывают как надо - моделируем так сказать, ситуацию, когда два процесса проверили - и оба получили, что записи нет - оба пытаются вставить, что нехорошо :).


MOA   (2005-07-18 11:43:00) [4]

>Fay ©   (18.07.05 11:34) [28]
>INSERT-ом проверял?
Угу. Во втором сеансе запускалось почти то же:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
IF EXISTS(SELECT * FROM t4 WITH (UPDLOCK) WHERE f1=3)
BEGIN
WAITFOR DELAY '00:00:05'
UPDATE t4 SET f2=2223 WHERE f1=3
END
ELSE
BEGIN
WAITFOR DELAY '00:00:05'
INSERT INTO t4 (f1, f2, f3) VALUES (3, 2003, 3003)
END
COMMIT TRANSACTION

Результат - всё как надо, ждёт инсерта с первого сеанса, потом апдейтит (записи с f1=3 в таблице первоначально нет).


evvcom   (2005-07-18 11:38:00) [5]


> WAITFOR DELAY '00:00:05'

А это зачем? Искусственные тормоза? Делай [2] и хватит ерундой заниматься с кучей лишних запросов, да еще искусственных задержек.


Fay   (2005-07-18 11:34:00) [6]

2 MOA ©   (18.07.05 11:02) [22]
INSERT-ом проверял?


evvcom   (2005-07-18 11:19:00) [7]

А [6], кстати, может быть чревато последствиями. Нехорошими
еще с большей вероятностью. Имхо.


evvcom   (2005-07-18 11:15:00) [8]


> что может быть чревато последствиями. Нехорошими

Сейчас в хелпе этого не увидел, но раньше читал, что если читать из @@ROWCOUNT сразу же за селектом, апдейтом и т.п., то это гарантирует, что она покажет именно нужное значение. А иначе зачем было мелкомягким вводить такую переменную, если ей нельзя доверять на 100%?


ЮЮ   (2005-07-18 11:15:00) [9]

Честно говоря, хотелось бы автора услушать, откуда такое желание возникло, точнее откуда это f1 взялось.

Если из этой же базы, то к чему такие извращения. Ведь если f1 определен, то запись есть и её надо редактировать. Даже если её уже не стало, то зачем вставлять, если её только что кто-то удалил? А если запись новая, то откуда f1 на клиенте? Его должен тогда сервер определить, ибо два клиента по одному и тому же алгоритму получат одно и тоже значение для новой записи, а это не лучше, чем в случае Fay ©   (18.07.05 10:17) [19]

Если же это внешние данные, то ситуация описанная в [19]
тоже притянута за уши, т.к. если из двух разных пакетов путаются вставить разные записи (разные f2 или f3 для одинакового f1), то это уже ошибка, независимо от поведения сервера, а если одинаковые, то не важно из какого пакета она добавится. А добавление 2х записей невозможно ввиду " f1 уникальны"


ЮЮ   (2005-07-18 11:14:00) [10]

>В [2] ты привязываешься к глобальной переменной @@ROWCOUNT

Может тогда и @@ERROR небезопасно смотреть, ведь там может оказаться чужая ошибка :)
if @@ROWCOUNT = 0 - впримере из BOL стоит


Ega23   (2005-07-18 11:03:00) [11]

2 evvcom ©   (18.07.05 10:29) [21]
А [2] что такое?

В [2] ты привязываешься к глобальной переменной @@ROWCOUNT, что может быть чревато последствиями. Нехорошими.


MOA   (2005-07-18 11:02:00) [12]

Прошло вот так:

CREATE TABLE [t4] (
[f1] [int] NOT NULL ,
[f2] [int] NULL ,
[f3] [int] NULL ,
CONSTRAINT [PK_t4] PRIMARY KEY  CLUSTERED
(
 [f1]
)  ON [PRIMARY]
) ON [PRIMARY]
GO

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
IF EXISTS(SELECT * FROM t4 WITH (UPDLOCK) WHERE f1=3)
BEGIN
WAITFOR DELAY '00:00:05'
UPDATE t4 SET f2=223 WHERE f1=3
END
ELSE
BEGIN
WAITFOR DELAY '00:00:05'
INSERT INTO t4 (f1, f2, f3) VALUES (3, 203, 303)
END
COMMIT TRANSACTION

Т.е. с уровнем транзакции SERIALIZABLE и хинтом на экзисте UPDLOCK - всё ждёт как надо кого надо ;).


evvcom   (2005-07-18 10:29:00) [13]


> Честно говоря, я ждал Вышего решения задачи, а не проповеди

А [2] что такое?


Ega23   (2005-07-18 10:20:00) [14]

2 Fay ©   (18.07.05 10:17) [19]

Ты меня опередил...  :о)


Fay   (2005-07-18 10:17:00) [15]

2 evvcom ©   (18.07.05 10:06) [18]
Честно говоря, я ждал Вышего решения задачи, а не проповеди.

2 ЮЮ ©   (18.07.05 9:58) [14]
Открываем QA. В одном окне пишем
use pubs
go
if object_id('QWE') is not null
 drop table QWE
go
create table QWE(
CODE int not null,
NAME varchar(32) collate SQL_Latin1_General_CP1251_CI_AS not null,
constraint PK_QWE primary key nonclustered(CODE),
constraint UNQ_QWE_NAME unique(NAME)
)
go

insert into QWE (CODE, NAME) values (1, '1')
insert into QWE (CODE, NAME) values (2, '2')
insert into QWE (CODE, NAME) values (3, '3')
go

declare
 @n int,
 @s varchar(32),
 @dt datetime

select
 @n = 2,
 @s = 'Два',
 @dt = '00:00:05'

begin tran

if exists(select * from QWE where CODE = @n)
 begin
   waitfor delay @dt
   update QWE set NAME = @s where CODE = @n
 end
else
 begin
   waitfor delay @dt
   insert into QWE (CODE, NAME) values (@n, @s)
 end
 select [row count] = @@rowcount
commit tran
go
drop table QWE

, а в другом
use pubs
delete from QWE where CODE = 2


Запускаем сначала 1-й, и пока он думает, 2-й скрипт.
Внимательно смотрим на [row count]


evvcom   (2005-07-18 10:06:00) [16]


> Внимательно жду(ждём) подробностей.

А чего непонятно? В обоих случаях используется сначала select (1-ый скан), потом update (2-ой скан). А индексы тут не при чем, они на количество сканов никак не влияют. На продолжительность (объем перебора и т.п.) да, но на количество...


Anatoly Podgoretsky   (2005-07-18 10:01:00) [17]

Она естественно никуда не денется, но может оказаться добавленой в промежутке между SELECT и INSERT


Fay   (2005-07-18 10:00:00) [18]

2 ЮЮ ©   (18.07.05 9:58) [14]
... или появится


Fay   (2005-07-18 10:00:00) [19]

2 ЮЮ ©   (18.07.05 9:58) [14]
Денется, ещё как.

2 Anatoly Podgoretsky ©   (18.07.05 9:56) [13]
А что Вы имели ввиду, говоря про наличие таких триггеров?


ЮЮ   (2005-07-18 09:58:00) [20]

>Удача явно потребуется, т.к. между
>IF EXISTS(SELECT * FROM t WHERE f1=..)
>и
>UPDATE ....
>запись может быть удалена/добавлена

Если в рамках одной транзакции, а между ними нет закрытия ожной и старта новой транзакции, то никуда она не денется


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо