Недопустимое использование оператора с побочным действием
als-a Откуда: | Не пойму что не так (ногами не бейте вчера MsSql Server 2005 Rus поставил) в Microsoft SQL Server Management Studio (9.00.2047.00) пытаюсь создать фунцию вот текст — ================================================ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO — ============================================= CREATE FUNCTION GET_ID ( — Add the parameters for the function here ) RETURNS int AS BEGIN DECLARE @a int, @ID_COUNT_0 int Select @ID_COUNT_0=ID_COUNT_0 from dbo.Counters Set @a=@ID_COUNT_0 Set @ID_COUNT_0=@ID_COUNT_0+1 Update dbo.Counters set ID_COUNT_0 = @ID_COUNT_0 END Сообщение 443, уровень 16, состояние 15, процедура GET_ID, строка 17 Таблица dbo.Counters состоит из одного столбца int в ней одна запись где ID_COUNT_0=1 |
daw Откуда: Муром -> Москва | в функциях запрещены dml операторы над постоянными таблицами. Posted via ActualForum NNTP Server 1.4 |
Glory Откуда: |
А что непонятного в сообщении |
als-a Откуда: | а процедуры ? |
Glory Откуда: | Двести |
daw Откуда: Муром -> Москва | >а процедуры ? в процедурах — можно. но процедуры нельзя напрямую в запросах использовать. Posted via ActualForum NNTP Server 1.4 |
daw Откуда: Муром -> Москва | >а процедуры ? или вы в смысле — вызывать процедуры в функциях? Posted via ActualForum NNTP Server 1.4 |
als-a Откуда: | То есть запихнуть Update в процедуру и вызвать процедуру из функции тоже не прокатит ? |
проходящий. Guest |
Ничего не знаю, ничего не понимаю, но первое что сделаю — свой генератор последовательностей. |
Glory Откуда: |
Можно один раз открыть в хелпе перечень ограничений udf-ов и узнать о них всех сразу |
pkarklin Откуда: Москва (Муром) |
ну и делайте на основе процедуры. |
als-a Откуда: | Ну по поводу Ничего не знаю, ни чего не понимаю: Я более 10 лет работал с Oracle. а по поводу но первое что сделаю — свой генератор последовательностей. Без него ж никак! : на чем-то надо ж эксперементы проводить… Кстати в Oracle в фунции можно писать что угодно, чего-то парни из Microsoft не додумали … |
Гавриленко Сергей Алексеевич Откуда: Moscow |
У вас два варианта: или отвыкать от того, к чему вы привыкли на оракле, или писать дальше на оракле. |
pkarklin Откуда: Москва (Муром) |
М.б. свойством IDENTITY(1, 1) обойдетесь?! |
als-a Откуда: | да обойтись можно то можно а как же эксперименты ? |
Glory Откуда: |
После 10лет работы с Oracle это скорее будут не эксперименты, а попытки эмулировать Oracle на MSSQL |
pkarklin Откуда: Москва (Муром) |
О каких экспериментах идет речь?! Попытка реализовать на MS SQL Oracle? |
als-a Откуда: |
В другое место ушел работать, на Oracle золотого запаса здесь не хватает. Тут базы под акцесом сделаны, так то это не очень хорошо … Так что надо потихонечку мигрировать куда — нибудь, похоже на MS SQL Server ….. |
als-a Откуда: | да и под нарезанные задачи — Oracle все равно что из пушки по воробьям … |
pkarklin Откуда: Москва (Муром) |
Тогда резко забываем об Oracle и осваиваем «парадигму» MS SQL. 😉 |
tpg Откуда: Novosibirsk |
С чего это вы решили, что не додумали? Половина команды разработки сиквела — это аккурат бывшие разработчики оракла. Видимо таким образом они решили отказаться от тупиковых путей (перейдя в MS) 😉 |
SQLMantis Откуда: Москва | Если бы подобное было разрешено, что вернул бы запрос: select GET_ID, ID_COUNT_0 from dbo.Counters ? |
Ссылка на сообщение
Ссылка (включая название темы)
Ссылка (URL)
x
Multy Откуда: | Пытаемся создать функцию типа Create FUNCTION dbo.Ins ( @Pr1 Int, @Pr2 Int ) RETURNS @Rez1 TABLE ( Rez1 Int, Rez2 Int ) AS BEGIN insert into dbo.Rez(Rez1,Rez2) Values(@Pr1,@Pr2) insert into @Rez Values(1,1) RETURN END Получаем ошибку: Сообщение 443, уровень 16, состояние 15, процедура Insert, строка 13 Недопустимое использование оператора «INS», оказывающего побочное действие, в функции. Это можно как-нибудь обойти или отключить? Alter Procedure dbo.Ins ( @Pr1 Int, @Pr2 Int ) AS BEGIN insert into dbo.Rez(Rez1,Rez2) Values(@Pr1,@Pr2) Select * from dbo.Rez END Или инсерты взможны только в процедурах? |
Nailbomb Guest | в функциях инсерты делать нельзя |
Multy Откуда: |
Это они не доработали, или скорее переработали… |
Гавриленко Сергей Алексеевич Откуда: Moscow |
Да нет, это просто кто-то хелп не дочитал. |
Козьма Прутков Откуда: Москва | Multy, а точно надо писать dbo.Rez а не @Rez1? В результирующую таблицу инсенртить можно, а в остальные — нет. Create FUNCTION dbo.Ins |
Multy Откуда: |
В результирующию то понятно, смысл был как раз в побочную таблицу. |
Козьма Прутков Откуда: Москва | Multy, а что за задача такая, при которой надо что-то менять в обычных таблицах? Уж не генератор ли каких номеров, или упаси бог ключей, вы пытаетесь написать? |
проходящий. Guest |
И есть достаточное обоснование такой надобности? Можно его глянуть? |
Пятница_13 Guest | Козьма Прутков, А вот тут подробнее ! Про ключи особенно. |
Aleksey-K Откуда: Москва |
Это не совсем верная информация. |
Козьма Прутков Откуда: Москва | Aleksey-K, ладно уж придираться-то, я оперирую в терминах вопроса, а не пытаюсь пересказать BOL 🙂 |
Козьма Прутков Откуда: Москва |
Даже не знаю, что ответить. Может, лучше вопрос переформулировать? Есть просто любители писать генераторы ключей, 99% которых просто не знают, как воспользоваться уже имеющимися возможностями MSSQL, или возможностями технологии разработки кода, который работает с БД. Поскольку любителей таких много — потому сразу и спрашиваю. |
Пятница_13 Guest |
Да, надо признать — я один из тех. А может просто привычка после Firebird-а и Oracle-а. |
Козьма Прутков Откуда: Москва | Пятница_13, не вижу смысла своими словами рассказывать, почитайте в BOL про identity, @@identity, scope_identity(). А также uniqueidentifier, newid() если хочется глобальной уникальности при невысокой производительности. Будут конкретные вопросы — задавайте уже их. |
Пятница_13 Guest | Козьма Прутков, Предлагаете изменить привычкам ? |
Glory Откуда: |
Непривычно == некрасиво ? Красивость мереется по длине кода ? |
Пятница_13 Guest |
В т.ч. и по длине кода )) |
Ссылка на сообщение
Ссылка (включая название темы)
Ссылка (URL)
x
ValGer Откуда: Псков | Казалось бы тривиальная задачка. Хочу создать функцию, которая бы выдавала наружу код новой записи в таблице. Код автоинкрементный, с шагом +1. Это достигается чтением @@IDENTITY после создания новой строки. Пишу функцию (в студии SQL 2008 R2): ALTER FUNCTION [dbo].[НомерНовогоРаботника] INSERT INTO dbo.MAIN RETURN @@IDENTITY Проверка синтаксиса в студии говорит, что всё хорошо, но как только пытаюсь выполнить (то есть записать эту функцию в базу — ALTER) выдаётся странная ошибка: Сообщение 443, уровень 16, состояние 15, процедура НомерНовогоРаботника, строка 7 Проверил отдельно INSERT — всё прекрасно вставляется. |
locky Откуда: Харьков, Украина |
это означает ровно то, что написано — «нельзя использовать insert в функции» — равно как и еще некоторый набор стейтментов |
iap Откуда: Москва | ValGer, из UDF нельзя менять данные в постоянных и временных таблицах. |
ValGer Откуда: Псков | locky, Спасибо, просветили! Читая книжки, наверно, пропустил. |
locky Откуда: Харьков, Украина |
Топ 10, вопрос №4 |
ValGer Откуда: Псков | iap, Здесь я побывал, но нигде членораздельные слова о том, что INSERT нельзя использовать в функциях не встретил. А сообщение очень завуалированное — спасибо просветили. |
Ennor Tiegael Откуда: | ValGer, На самом деле, insert использовать в функциях можно, но только с табличными переменными (они пока по определению локальны). Общее же правило — выполнение функции не должно приводить к изменению чего-либо за ее пределами — сформулировано в доке довольно четко. |
locky Откуда: Харьков, Украина |
https://msdn.microsoft.com/ru-ru/library/ms186755(v=sql.100).aspx разделы «Совместимость» и «Ограничения» https://msdn.microsoft.com/ru-ru/library/ms191320(v=sql.100).aspx раздел «Рекомендации»: «Изменения таблиц баз данных, операции с курсорами, не являющимися локальными для данной функции, отправка электронной почты, попытка изменения каталога, формирование результирующего набора, возвращаемого пользователю — это примеры действий, выполнение которых внутри функции невозможно.» |
SIMPLicity_ Откуда: (((@))) | Перепишите на хранимую процедуру,- проблем со вставкой не будет. первой строкой set nocount on в последней — select @NewId (который у Вас @@identity) |
Ссылка на сообщение
Ссылка (включая название темы)
Ссылка (URL)
x
Автор: Gwire 5.2.2012, 04:46 | ||||||
Доброго здоровья. Я проектирую базу, которая будет еще в дальнейшем изменяться и расти, по мере поступления требований от заказчика. (Может, требования и не поступят, но лучше на это заложиться) Каждая таблица имеет поле [id] которое primary key. Идея моей проблемы такова. Что это значит. Например: Выполнив запрос «SELECT *, Get_Using_Count(‘dbo.Накладные’, [id]) FROM [Накладные]», Следующий код формирует уже готовые запросы на выборку для каждой связанной таблицы с указанной.
На ваших базах она тоже отработает ничего не переделывая (только тип @ID, возможно) Натравив на нее CURSOR я намеревался собрать их в одну строку и выполнить
Но вот не задача — я не могу выполнить EXEC, так чтобы он мне вернул результат не на экран а в переменную.
Но возникает вторая проблема которую я не смог побороть Возникает в строчке *2* Вопрос: |
Автор: tzirechnoy 5.2.2012, 10:33 |
То есть, если Вам вдруг захочется, допустим, создать к накладным список необходимых подписей, подключить его через классическое многие-ко-многим и прописать дефолт — то вся Ваша изящная схема успешно накернится. Или, допустим, не Вам, а следующему программисту, ковыряющему эту опердень. Он будет рад, вероятно. В общем, не выпендривайтесь. Перечислите список зависимых таблиц и полей явно. Если очень хочется сделать одну абстракцыю в БД, отвечающую за это — вынесите во view. Впрочем, по-моему, дажэ в этом смысла нет: оно, скорее всего, нужно строго в одном месте — потому делайте просто запросом, без функцый и прочих наворотов. |
Автор: Gwire 5.2.2012, 15:46 | ||||
Я никогда не связываю таблицы этим методом. Это плохая практика. В моем случаи «классическое многие-ко-многим» совсем не классическое .
Другого программиста не будет. У меня заказчик родной дядя. |
Автор: Gwire 5.2.2012, 18:06 | ||||||
Нет. Обычный внешний ключ, не позволяющий удалять если есть связи. Логика такова: если запись попала в базу и к ней были добавлены связанные записи, она не может быть удалена. Мне эта функция нужна для информативности. Что бы оператор понимал какие записи (накладные, товары, клиенты, адреса …) являются «мусором». Для чистки базы от этого «мусора» (вручную. Возможно какие-то записи будут добавлены наперед, и об этом знает только оператор).
Как я уже сказал я не использую каскадные операций.
Логически они существуют, как в моем примере. Но в базе нет таблиц связанных между собой методом «многие-ко-многим». |
Автор: Zloxa 5.2.2012, 20:15 | ||||||
Ваш пример описал физическую реализацию связи многие ко многим.
Для того, чтобы вы этого не смогли и устанавливаются внешние ключи, зачем дублировать их функционал собственным велосипедом? (других версий, оправдывающих такое желание, кроме касскадов, я высосать из пальца не смог ) Тем более что вы врядли сможете его реализовать более эффективно нежели это уже сделано на стороне СУБД. Вы не думали над тем, что в процессе вычисления вашей функции, могут измениться данные, повлиявшие на ее результат? Например вы удаляете товар: функция уже просмотрела таблицу накладных, стала смотреть в таблице остатков, а в это время другой пользователь создал накладную, которая приходует удаляемый вами товар, а к тому моменту, как функция закончит свою работу, вполне возможно, товар уже будет проведен и по остаткам. Как вы полагали избегать такой ситуации? Захватывать в монопольный доступ все объекты базы, которые используют товар? Проверка по внешним ключам, эту задачу решает куда меньшим количеством ресурсов. Пытаемся удалить запись, если попытка обламывается с ошибкой по нарушению внешнего ключа, размечаем запись как не активную — и все. |
Автор: Gwire 6.2.2012, 05:11 | ||||||||||||
Zloxa, у меня складывается впечатление, что Вы читаете посты через слово или не особо разбираетесь в разнице между связями таблица-таблица и сущность-сущность. Вы о какой связи думали когда писали:
По всей видимости это была связь сущность-сущность. Потому как ваша реакция, оправдана только в этом случае.
Здесь, Вы уже говорите о таблицах, где я с вами солидарен, тем более, что я всегда говорил о таблицах. Связь между не уникальным полем одной таблицы и не уникальным полем другой таблицы — это простая формулировка связи многие-ко-многим между таблицами. Именно от этих связей лучше избавляться. Именно они являются плохой практикой. А то что, связь между сущностями многие-ко-многим —
ни кто не спорит.
Во первых: один пользователь не может удалять накладные другого, если не имеет определенных привилегий.
Имелось ввиду, что оператор принимает решение, что является «мусором». Программа, со своей стороны, просто
Так и реализовано. Но этот метод не подходит для того, что бы просто посмотреть «пустая» запись или нет. |
Автор: Zloxa 6.2.2012, 09:55 | ||||
Вы заблуждаетесь, когда называете «Связь между не уникальным полем одной таблицы и не уникальным полем другой таблицы» отношением многие-ко-многим. На основании этого заблуждения вы заявили, что связи многие-ко-многим — плохая практика, которую следует избегать. Я оспариваю исключительно этот тезис. То что под связью многие-ко-многим вы имеете в виду вовсе не связь многие-ко-многим, нисколь не нивелирует абсурдности вашего заявления. Если это ваше, столь же уверенное, сколь и абсурдное зявление прочтет новичек, это, определенно, может сбить его с толку, пустить по ложному пути развития. Лишь по этой причине я его так настойчиво оспариваю.
Вы еще и в запросе собираетесь эту функцию использовать? |
Автор: Gwire 6.2.2012, 14:48 | ||||
Zloxa, прошу прощения. MS SQL действительно не умеет создавать настоящие связи многие-ко-многим между двумя таблицами. Моя ошибка не проверил. Потому как был уверен что, все СУБД это умеют (точно могут FoxPro для dos, Access 2003, и Oracle не помню версию). Теперь понятно почему у вас с Akina, мои реплики вызвали негодование. MS SQL убрав возможность создавать такие связи не могла убрать самого понятия «многие-ко-многим», и они его перефразировали.
По всей видимости tzirechnoy тоже думал о тех-же «многие-ко-многим» что и я.
Теперь не вижу проблемы. Остается «первородный» вопрос: Точку зрения tzirechnoy я понял. Если совсем ничего не найдется — реализую обычным перечисление. |
Автор: Akina 6.2.2012, 15:03 | ||
Те СУБД, которые это умеют, на самом деле просто умеют создать эту самую дополнительную промежуточную связующую таблицу и далеко спрятать её от конечного пользователя. |
Автор: Gwire 6.2.2012, 15:23 |
Akina, так Вы согласны, что мое мнение не было ошибочным. И что Вы с Zloxa просто могли сказать, что MS SQL не поддерживает прямые связи такого типа (если конечно знали что бывает по другому). |
Автор: Akina 6.2.2012, 16:31 |
Gwire, да я вообще дилетант… но твёрдо знаю, что много-ко-много следует реализовывать через связующую таблицу, даже когда мне предлагают этот сервис в готовой форме (Аксесс-2003 не умеет, а 2007 умеет — но ничто не заставит меня этой возможностью воспользоваться). Ибо «всё, что ты не укажешь как именно делать, имеет право делаться как угодно» — а мне такого добра даром не надо. |
Автор: Zloxa 6.2.2012, 17:48 | ||||
Постарайтесь вспомнить. Мне очень интересно.
По всей видимости вы не поняли о чем говорил tzirechnoy. |