Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Вставка ODKU с условием

Добрый день!

Есть такой запрос:

SQL
1
INSERT INTO TABLE SET id=123, info=456 ON DUPLICATE KEY UPDATE info=456;
Как можно добавить в него условие, чтоб ODKU выполнялся только когда info=789 или IS NULL?
Ответ: Anvano, спасибо!

А вот я еще подумал, можно в условие CASE добавить проверку поля другой таблицы? Например, table2.fiel=1 ? Надо ж будет как-то заджойнить для ODKU эту table2, не пойму как именно это можно сделать...
Вопрос: Вставка ODKU с условием

Добрый день!

Есть такой запрос:

Код
INSERT INTO TABLE SET id=123, info=456 ON DUPLICATE KEY UPDATE info=456;


Как можно добавить в него условие, чтоб ODKU выполнялся только когда info=789 или IS NULL?
Ответ:
Цитата(maxipub @  27.9.2016,  16:10 )
чтобы INSERT/UPDATE выполнялся только тогда, когда для строчки table2.id=123 (id - уникальное поле) значение ячейки table2.stat='ok' ?

Ну дык ЭТО же фильтруется ещё в секции WHERE... что там не прошло контроля, в ODKU никак не попадёт.
Вопрос: Триггер запрет на вставку при условии не вхождения в диапазон даты

Есть таблица readers со столбцами (number, name, date_of_born, address, telephone, date_registration).
Нужно написать триггер чтоб было условие: при вставке данных в столбец date_registration вычиталось 16 YEAR и эта дата ('date_registration' - 16) была меньше вставляемой даты в столбец date_of_born в противном случае разрешить вставку данных, если условие выполняется - то запретить вставку.

Код MySQL
1
2
3
4
5
6
7
create trigger do_16 before insert on readers
for each row
begin
if (DATE_SUB(NEW.date_registration, interval 16 year) < NEW.date_of_born) then
INSERT INTO readers (number, name, date_of_born, address, telephone, date_registration) VALUES (NEW.number, NEW.name, NEW.date_of_born, NEW.address, NEW.telephone, NEW.date_registration);
end if;
end;
Выдает ошибки
ERROR 1193 (HY000): Unknown system variable 'begin'
mysql> end if;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'end i
f' at line 1
mysql> end;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'end'
at line 1
Ответ: drunja, delimiter само собой, а вот информацию об ошибке лучше передавать через SIGNAL:
Вопрос: 2 условия в 1 тригер

Добрый день!

Можно ли так сделать?

Есть 2 таблицы ("а","б")

я хочу сделать тригер,чтобы выполнялось условие:

когда из таблицы "а" произошла вставка строчки в таблицу "б", строчка из таблицы "а" удалилась

Delimiter $$
CREATE TRIGGER `insert_customer`
AFTER INSERT ON t2
FOR EACH ROW BEGIN

delete from t1 where id = new.id;
END;


ошибка Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
Ответ:
miksoft
кириллk
когда из таблицы "а" произошла вставка строчки в таблицу "б", строчка из таблицы "а" удалилась
кириллk
Мне нужно чтобы при вставке в таблицу А, происходила вставка в таблицу Б
А не проще две таблицы в одну объединить?
В качестве изврата можно сделать триггер на before delete исходной таблицы, в котором и будет и производиться вставка дынных во вторую.
Вопрос: Вставка НЕПОВТОРЯЮЩИХСЯ текстовых строк (nvarchar(4000))

Есть задача: в справочник (ID int primary key, Value nvarchar(4000)) нужно вставлять строки и получить на выходе ID новой строки или существующей (если есть таковая). Ограничение одно - строки не должны повторяться!
И тут настает сложность: поле Value - нельзя проиндексировать и установить уникальность на уровне индекса (ограничение SQL - 900 байт на индексируемое поле), а искать по нему надо.

Сложность задачи еще в том, что это будет высоконагруженный блок с большим кол-вом данных (млн+) в котором данные льются с большой скоростью. И вставка должна быть максимально быстрой....

Чтобы ускорить поиск по текстовому полю - мы ввели поле ValueHash bigint (индексируем это поле). Теперь поиск получается по ValueHash быстрым - но это не гарантия выбора единственной записи...

В итоге - Если использовать IF (NOT EXISTS(...)) INSERT INTO... (или MERGE - что похоже) то все равно складывается ситуация, когда 2 потока могут вставить запись с одинаковым Value (при уровне изоляции транзакции меньше чем SERIALIZABLE - а если SERIALIZABLE - то дэдлок).

Помогите решить вопрос - наверняка кто-то сталкивался с такой задачей в больших системах... Нужно организовать вставку с получением ID без задвоения Value и без дэдлоков...

Прикладываю хранимку на вставку...

CREATE PROCEDURE dbo.ModuleNameInsertValue
	@value nvarchar(4000),
	@valueHash bigint
AS
SET NOCOUNT ON;

-- переменная для возврата значения
declare @Id int	SET @Id = 0

--SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION 

BEGIN TRY  
	-- сливаем записи в @hashed - точность хеша не 100%, но сюда попадется очень МАЛО (чаще всего одна) записей полюбасу
	declare @hashed table (Id int, [Value] nvarchar(4000), [ValueHash] bigint)
	INSERT INTO @hashed
		SELECT Id, [Value], [ValueHash] FROM [dbo].[ModuleName] WHERE [valueHash] = @valueHash

	-- т.к. записей мало - то даже поиск по nvarchar(4000) будет быстрым
	SELECT @Id = Id FROM @hashed WHERE [ValueHash] = @valueHash AND [Value] = @value -- тут уже точно одна
	IF (@Id = 0) BEGIN
		INSERT INTO dbo.[ModuleName] ([Value], [ValueHash]) VALUES (@value, @valueHash)
		SET @Id = SCOPE_IDENTITY(); 
	END
	IF @@TRANCOUNT > 0  COMMIT TRANSACTION
END TRY  
BEGIN CATCH  
	BEGIN
		IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
		THROW;
	END
END CATCH;



RETURN @Id
GO
Ответ:
balykovdron
Спасибо всем, в моем случае проблема решилась благодаря решению [invm], отдельное спасибо ему. Ни разу мои многопоточные тесты не выявили нарушения условий вставки.

CREATE PROCEDURE dbo.ModuleNameInsertValue
	@value nvarchar(4000),
	@valueHash bigint
AS
SET NOCOUNT ON;

-- переменная для возврата значения
declare @Id int	

insert into dbo.ModuleName ([Value], ValueHash)
  select  @value, @valueHash
  where not exists(select * from dbo.ModuleName with (updlock, serializable) WHERE ValueHash = @valueHash and [Value] = @value);

if @@rowcount > 0
  select @id = scope_identity()
else
  select @id = id from dbo.ModuleName WHERE ValueHash = @valueHash and [Value] = @value;

RETURN @Id
GO

И эти люди запрещают нам ковырять в носу!

balykovdron
высоконагруженный блок с большим кол-вом данных (млн+)


1. нахрена декларация ненужной переменной?
2. нахрена ненужное присваивание?

if @@rowcount > 0 return scope_identity();

RETURN (select id from dbo.ModuleName WHERE ValueHash = @valueHash and [Value] = @value)
Вопрос: Вставка с выбором.

Дано.
Есть таблица A с двумя столбцами (Aa и Ab). С данными.
Есть таблица B с одним столбцом (Bc). Пустая.

Требуется.
Произвести вставку данных из A в B таким образом, чтобы каждая десятая (сотая/тысячная) строка брала данные из столбца Ab, а все остальные из столбца Aa.

Сделал через курсор и третий столбец, но наверняка можно сделать триггером (и возможно ещё как-то). Хотелось бы узнать как именно.
Заранее благодарю!

Вот использованный курсор. Точнее два курсора.

declare 
    id B.id%TYPE; -- числа по порядку начиная с 1
    Ba B.Ba%TYPE; 
    Bb B.Bb%TYPE; 
    Bc B.Bc%TYPE; -- пустой столбец
    
    CURSOR B_Cursor IS
        SELECT id, Ba, Bb, Bc 
        FROM B where mod(id, 50)<>0 FOR UPDATE;
    
begin
    OPEN B_Cursor;
    LOOP 
    FETCH B_Cursor INTO id, Ba, Bb, Bc;
    EXIT WHEN B_Cursor%NOTFOUND;
    DELETE FROM B WHERE CURRENT OF B_Cursor;
    INSERT INTO B VALUES(id, Ba, Bb, Ba);
    END LOOP;
    CLOSE B_Cursor;
end;
/


declare 
    id B.id%TYPE; 
    Ba B.Ba%TYPE; 
    Bb B.Bb%TYPE; 
    Bc B.Bc%TYPE; 
    
    CURSOR B_Cursor IS
        SELECT id, Ba, Bb, Bc 
        FROM B where Bc is null FOR UPDATE;
    
begin
    OPEN B_Cursor;
    LOOP 
    FETCH B_Cursor INTO id, Ba, Bb, Bc;
    EXIT WHEN B_Cursor%NOTFOUND;
    DELETE FROM B WHERE CURRENT OF B_Cursor;
    INSERT INTO B VALUES(id, Ba, Bb, Bb);
    END LOOP;
    CLOSE B_Cursor;
end;
/
Ответ:
roadster
loky1109
Да, три раза.
что три раза?
дырки же будут.
тогда непонятно условие "каждые n записей, потому как его при таком подходе сложно соблюсти.


id выдаётся при создании таблицы A, а там вставка безусловная.
Вопрос: Вставка данных по условиям в excel

Здравствуйте,

Подскажите, пожалуйста, как можно вставить данные из access в excel. Есть таблица в access из нее по определенным условиям нужно выбрать данные и вставить их в определенные ячейки в excel. Если данные выбирать через команду

Visual Basic
1
2
3
4
cn.ConnectionString = "Provider=microsoft.ace.oledb.12.0; data source=" & Path
cn.Open
A = cn.Execute(select sum([F]) from Table where ([A]= 1 and [B]=2 and [C]=3).GetString
Range("A1")=A
то так как данных для выбора очень много, то получается что команда очень долго выполняет действие. Можно ли выбрать данные через Recordset?

Visual Basic
1
2
3
4
connDB.ConnectionString = "Provider=Microsoft.ace.oledb.12.0;data source=" & Path
connDB.Open
Set rs = connDB.Execute("Select * from " & Table)
Range("A2").CopyFromRecordset rs
Т. е. написать не CopyFromRecordset, а условие по которым будут выбираться данные? Спасибо.
Ответ: В Recordset будет скопировано таблица, состоящая из 5 столбцов, 4 столбца это условия а 5 столбец значение. Условия будут записаны в ячейки в excel. Например A1="Условие1", A2="Условие2", A3="Условие3", A4="Условие4". Нужно в макросе написать что если столбец1 в рекордсет равен ячейки А1 и столбец2 в рекордсет равен ячейки А2 и столбец 3 в рекродсет равен А3 и т. д., то в ячейку В1 выводится значение из столбца 5 в рекордсете. Спасибо.

Добавлено через 22 минуты
И таких значений, которые нужно будет получить будет 150
Вопрос: Postgres 9.5:"INSERT INTO ... ON CONFLICT" - Как понять произошла вставка или обновление?

Postgres 9.5
Как в конструкции
   INSERT INTO table (Id, Name)
        VALUES (:in_Id, :in_Name)
   ON CONFLICT (Id)
            DO             
        UPDATE 
           SET name = :in_name


понять какая операция была выполнена - вставка или обновление?

В Firebird в аналогичной конструкции "UPDATE OR INSERT" это достигается так:
   UPDATE OR INSERT INTO table (Id, Name) VALUES (:in_Id, :in_Name) RETURNING OLD.Id


т.е можно указать префикс перед возвращаемым PK: если он NULL, то произошла вставка...

А как получить информацию о том была вставка или обновление в Postgres?
Ответ: shaposh,

можно решить эту проблему путём использования системной невидимой колонки xmax



тест
CREATE TABLE account
(
  id bigserial,
  name varchar,
  surname varchar,
  address varchar,
  PRIMARY KEY (id),
  CONSTRAINT unique_person UNIQUE (name, surname, address)
);

INSERT INTO account as a (id, name, surname, address)
VALUES (1, 'Вася', 'Пупкин', 'Москва, Кремль')
ON CONFLICT (id)
DO UPDATE SET
name=EXCLUDED.name || ' (бывший ' || a.name || ')',
surname=EXCLUDED.surname || ' (бывший ' || a.surname || ')'
returning xmax, * ;

xmax	id	name	surname	address
0	1	Вася	Пупкин	Москва, Кремль

INSERT INTO account AS a (id, name, surname, address)
VALUES (1, 'Петя', 'Петров', 'Москва, Кремль')
ON CONFLICT (id)
DO UPDATE SET
name=EXCLUDED.name || ' (бывший ' || a.name || ')',
surname=EXCLUDED.surname || ' (бывший ' || a.surname || ')'
returning xmax, * ;

xmax	       id	name	                        surname	                        address
22087375	1	Петя (бывший Вася)	Петров (бывший Пупкин)	Москва, Кремль


т.е.
0 - выполнена вставка
не 0 - выполнен update
Вопрос: Долгая вставка записей к париционированную таблицу

Досталась мне БД на Oracle 10g. В этой базе есть партиционированная таблица с локальными индексами main_table. В эту таблицу регулярно происходит вставка записей через конструкцию insert into main_table select distinct * from reserv.
Обычно время вставки 20 тыщ записей занимает 4-5 минут. Но, время от времени, периодами в несколько недель время вставки возрастает до 20-25 минут. Потом опять уменьшается. И так регулярно.
Видимых затыков в базе во время данных проблем не обнаружено. Перезагрука БД не помогает. Что может быть? В какую сторону копать?
Ответ: Valergrad,
Дольше всего из объектов ожидался одни из уникальных индексов в таблице, куда происходит вставка записей.
Вопрос: Вставка данных

Всем привет!
Столкнулся с задачей, но подобных случаев в сети отрыть не смог. Поэтому хотел бы прояснить несколько моментов о вставке данных.
Код Oracle 11 SQL
1
2
3
4
5
6
7
8
9
DECLARE
 
BEGIN
FOR c IN (SELECT * FROM table1)
LOOP
UPDATE table2 t2 SET td.arg2  = с.arg1
WHERE  с.id = t2.id
END LOOP;
END;
то есть тут используется неявное задание курсора. Как сделать так, чтобы каждое значение в td.arg2 поменялось на t1.arg1 там, где совпадают айдишники таблиц? Я так понял, что нужно использовать в секции декларирования переменную или я что-то путаю?
Заранее спасибо!
Ответ:
Цитата Сообщение от lehakarlov Посмотреть сообщение
нужно использовать в секции декларирования переменную или я что-то путаю
Во-первых, почему "Вставка данных", хотя тут изменение?
Во-вторых, можно курсор декларировать, можно так, как в примере.
Код SQL
1
2
3
4
5
6
DECLARE
   CURSOR C1
   IS
   SELECT ...
BEGIN
   FOR R1 IN C1 loop
Лично я предпочитаю способ с декларированием, поскольку он ИМХО нагляднее (особенно, если текст курсора достаточно большой), но вообще это дело вкуса.
В-третьих, приведенная задача (если это конечно не упрощенный пример) вполне решается на чистом SQL без использования PL/SQL.