обновляемый вид дает ошибку времени выполнения в Visual Basic

Я пытаюсь преобразовать старую программу Visual Basic, которая использует устаревшие таблицы базы данных, в более современную и надежную реализацию. Он использует много varchars, когда он должен был использовать числа с плавающей запятой, чтобы дать конкретный пример, это делает код очень трудным для чтения, так как требуется много преобразований из числа с плавающей запятой в строку и обратно, чего я хочу избежать в новом приложении)

Чтобы сохранить совместимость с предыдущими версиями, я создаю обновляемые представления для своих новых таблиц, чтобы старое приложение в vb все еще могло работать, или, по крайней мере, это намерение.

У меня есть вид следующим образом:

SELECT        
ArtikelNummer, 
CataloogID, 
Artikel, 
isnull(CONVERT(nvarchar(5), breedte),'') Breedte,
isnull(CONVERT(nvarchar(5), Hoogte),'') Hoogte,
isnull(CONVERT(nvarchar(5), Diepte),'') Diepte,
isnull(CONVERT(nvarchar(5), Aantal),'') Aantal,
FROM            
Master.Orders_Catalogen_Artikels

а затем я создал триггеры вместо вставки и вместо триггеров обновления в этом представлении, чтобы сделать его обновляемым, и вручную протестировал эти триггеры, чтобы убедиться, что они в порядке и работают.

Однако, когда в качестве окончательного теста я пытаюсь запустить программу VB6, она не может выполнить вставку даже до того, как она будет выполнена. Код не работает в самом VB в OLE:

With MyDE.rsSelectedArtikel
.Fields("CataloogID").Value = Orders.cCataloogID
.Fields("Artikel").Value = Orders.cbArtikel
.Fields("Aantal").Value = Orders.cAantal  ---> fails here

Запрос, стоящий за rsSelectedArtikel, представляет собой простой выбор * из Orders_Catalogen_artikels, который является именем представления, которое я показал выше.

¨Ошибка выполнения, которую я получаю, -2147217887(8004e21), обычно указывает на неправильное использование типа или что-то в этом роде. Но Aantal правильно идентифицируется как nvarchar(5), когда я просматриваю столбцы представления.

Есть ли решение или обходной путь для такой проблемы?

Конечно, я мог бы продолжать использовать старое определение таблицы, используя строки для длины и ширины и т.п., и создать обновляемое представление для нового приложения, но мне кажется, что это неправильно.

Или я немного модифицирую приложение VB, у меня есть исходники, и сначала модифицирую модель данных, чтобы использовать поплавки для ширины, высоты и длины, но я предпочитаю оставить ее нетронутой.

Я бы надеялся, что обновляемые представления были ответом на такого рода проблемы.

ОБНОВЛЕНИЕ 1: добавление триггера обновления и триггера вставки

ALTER TRIGGER [dbo].[V_Orders_Catalogen_Artikels_Update] ON  [dbo].[Orders_Catalogen_Artikels] 
INSTEAD OF UPDATE
AS 
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for trigger here
UPDATE [Master].[Orders_Catalogen_Artikels]
SET [CataloogID] = inserted.CataloogID
   ,[Artikel] = inserted.Artikel
   ,[Breedte] = iif(inserted.Breedte = '',null,inserted.Breedte)
   ,[Hoogte] = iif(inserted.Hoogte = '',null,inserted.Hoogte)
   ,[Diepte] = iif(inserted.Diepte = '',null,inserted.Diepte)
   ,[Aantal] = iif(inserted.Aantal = '',null,inserted.Aantal)
   ,[OmschrijvingNL] = inserted.OmschrijvingNL
   ,[Positie] = inserted.Positie
   ,[EenheidsPrijs] = inserted.EenheidsPrijs
   ,[Opmerking] = inserted.Opmerking
   ,[PosNr] = inserted.PosNr
   ,[Binnenkleur] = inserted.Binnenkleur
   ,[BKleurFront] = inserted.BKleurFront
   ,[Frontkantdikte] = inserted.Frontkantdikte
   ,[Poothoogte] = inserted.Poothoogte
   ,[BTWcode] = inserted.BTWcode
   ,[Korpuskantdikte] = inserted.Korpuskantdikte
   ,[ManuelePrijs] = inserted.ManuelePrijs
   ,[OpmerkingFr] = inserted.OpmerkingFr
   ,[OmschrijvingFr] = inserted.OmschrijvingFr
   ,[ArtikelGroepID] = inserted.ArtikelGroepID
   ,[ArtikelID] = inserted.ArtikelID
   ,[VolgNr] = inserted.VolgNr
   ,[Klaar] = inserted.Klaar
   ,[ScanDatum] = inserted.ScanDatum
   ,[ScanOpm] = inserted.ScanDatum
   ,[OpZaaglijst] = inserted.OpZaaglijst
FROM inserted
WHERE [Master].[Orders_Catalogen_Artikels].ArtikelNummer = inserted.ArtikelNummer

END

ALTER TRIGGER [dbo].[V_Orders_Catalogen_Artikels_Insert] ON  [dbo].[Orders_Catalogen_Artikels] 
INSTEAD OF INSERT
AS 
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for trigger here
INSERT INTO [Master].[Orders_Catalogen_Artikels]
       ([CataloogID]
       ,[Artikel]
       ,[Breedte]
       ,[Hoogte]
       ,[Diepte]
       ,[Aantal]
       ,[OmschrijvingNL]
       ,[Positie]
       ,[EenheidsPrijs]
       ,[Opmerking]
       ,[PosNr]
       ,[Binnenkleur]
       ,[BKleurFront]
       ,[Frontkantdikte]
       ,[Poothoogte]
       ,[BTWcode]
       ,[Korpuskantdikte]
       ,[ManuelePrijs]
       ,[OpmerkingFr]
       ,[OmschrijvingFr]
       ,[ArtikelGroepID]
       ,[ArtikelID]
       ,[VolgNr]
       ,[Klaar]
       ,[ScanDatum]
       ,[ScanOpm]
       ,[OpZaaglijst])
       SELECT 
  [CataloogID]
  ,[Artikel]
  ,iif(ISNUMERIC(breedte+'e0')=1,convert(float,[Breedte]),null) as newbreedte
  ,iif(ISNUMERIC([Hoogte]+'e0')=1,convert(float,[Hoogte]),null) as newhoogte
  ,iif(ISNUMERIC([Diepte]+'e0')=1,convert(float,[Diepte]),null) as newdiepte
  ,iif(ISNUMERIC([Aantal]+'e0')=1,convert(float,[Aantal]),null) as newaantal
  ,[OmschrijvingNL]
  ,[Positie]
  ,[EenheidsPrijs]
  ,[Opmerking]
  ,[PosNr]
  ,[Binnenkleur]
  ,[BKleurFront]
  ,[Frontkantdikte]
  ,[Poothoogte]
  ,[BTWcode]
  ,[Korpuskantdikte]
  ,[ManuelePrijs]
  ,[OpmerkingFr]
  ,[OmschrijvingFr]
  ,[ArtikelGroepID]
  ,[ArtikelID]
  ,[VolgNr]
  ,[Klaar]
  ,[ScanDatum]
  ,[ScanOpm]
  ,[OpZaaglijst]
FROM inserted

END

person Philip Stuyck    schedule 12.12.2016    source источник
comment
80040e21 — это страшное DB_E_ERRORSOCCURRED, что означает, что что-то пошло не так, разберитесь сами. Обновление представления с помощью триггера INSTEAD OF с использованием местоположения динамического курсора на стороне сервера возможно (я пробовал это в T-SQL), и это должно использоваться ADO . Чтобы узнать наверняка, попробуйте проследить оператор с помощью SQL Profiler, чтобы увидеть, что он на самом деле делает. Включите события ошибок для максимальной полезности. Если ваш набор записей находится на стороне клиента или отключен, проблема, вероятно, будет заключаться в том, что ADO знает, что вы не можете обновлять вычисляемые столбцы, но базовый сценарий должен быть возможен.   -  person Jeroen Mostert    schedule 12.12.2016
comment
Я посмотрю завтра, чтобы изучить ваше предложение, но я думаю, что проблема на стороне клиента. Я не ожидаю обращения к серверу уже в точке, где происходит задание. Очень полезный комментарий спасибо.   -  person Philip Stuyck    schedule 12.12.2016
comment
Если проблема заключается в столбцах компьютера, потенциальным, но, возможно, очень ресурсоемким обходным путем является копирование его в новый набор записей, в котором столбцы не установлены как вычисляемые, что убедит ADO разрешать обновления — до тех пор, пока они делают это. SQL Server, триггер должен позаботиться обо всем остальном. Однако в этот момент вы должны изменить код (даже если это просто обертка набора записей), и стоит подумать, не следует ли что-то переписывать в любом случае. (Я также понятия не имею, работает ли это на самом деле. Прошло несколько лет с тех пор, как мне приходилось работать с ADO. :-))   -  person Jeroen Mostert    schedule 12.12.2016


Ответы (1)


«Обновляемый» вид — это неправильное название. Представление ничего не хранит. Столбцы с псевдонимами возвращают измененный вид данных в таблице.

В вашем примере у вас есть два возможных пути кода для одного значения (null или не null). Вы пытаетесь отправить код обратно по одному из путей кода, чтобы получить базовое значение. Если, например, вы отправили '' по пути, как SQL узнает, должно ли это быть литералом '' или значением NULL, которое было заменено.

По этой причине вы не можете обновлять любые столбцы, содержащие выражение. Выражение фактически доступно только для чтения в представлении.

person Wes H    schedule 12.12.2016
comment
Я объяснил, что использовал вместо триггеров, чтобы сделать вид обновляемым. Эти триггеры обрабатывают то же самое, но в обратном порядке от того, что делает представление. - person Philip Stuyck; 13.12.2016
comment
Просто чтобы я понял, вы используете вместо триггера представление. Когда оператор пытается обновить представление, триггер берет на себя управление и вместо этого запускает оператор обновления. - person Wes H; 13.12.2016
comment
Если мое утверждение выше верно, можете ли вы опубликовать определение своего триггера? - person Wes H; 13.12.2016
comment
сделано, и вставка, и триггер обновления переводят пробел в нуль, представление переводит пробел в нуль. Для ширины, длины и т.п., если они хранятся в строке, если нет значения (0 является значением), пустая строка выглядит приемлемой. Ну, не для меня, потому что хранение чисел в строках - не мой первый выбор ;-) - person Philip Stuyck; 15.12.2016