DrgIonuţ Ответов: 1

Как выполнить хранимую процедуру с параметрами?


У меня есть база данных с 40 таблицами. Я хочу выбрать данные из определенной таблицы с помощью одной хранимой процедуры. Первая таблица (TblSPAU1) имеет 6 столбцов, название: идентификатор, COL_SPAU1_EA, COL_SPAU1_EQ, COL_SPAU1_ore, COL_SPAU1_nivel, даты и времени. Четвертая таблица (TblSPAU4), например, имеет эти 6 столбцов: Идентификатор COL_SPAU4_EA, COL_SPAU4_EQ, COL_SPAU4_ore, COL_SPAU4_nivel, даты и времени. Поэтому я хочу выбрать данные из таблицы X от DateStart до DateStop.

Я хочу выбрать, скажем, столбец ID и fist из определенной таблицы. @val представляет номер таблицы, из которой я хочу выбрать данные. На sp_sqlexec у меня есть подсказка, которая говорит, что у меня указано слишком много аргументов. Когда я выполняю EXEC, он выдает мне эту ошибку: Msg 137, Уровень 15, состояние 2, строка 1. Необходимо объявить скалярную переменную "@sql" Мой вопрос заключается в том, как я должен выполнить эту хранимую процедуру? Заранее большое спасибо!

Что я уже пробовал:

USE [DBRapBreaza]
GO
/****** Object:  StoredProcedure [dbo].[PS_SpauOPompa]    Script Date: 12/19/2018 15:48:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[PS_SpauOPompa]

@DataStart datetime,
@DataStop datetime,
@val int
AS
BEGIN
SET NOCOUNT ON;

declare @sql NVARCHAR(max)
declare @col1 varchar
set @col1='ID'
declare @col2 varchar(25) 
set @col2='COL_SPAU'+CONVERT(VARCHAR, @val)+'_EA' 
declare @col3 varchar 
set @col3='DateTime'

set @sql='select [ID]'+@col2+' FROM [DBRapBreaza].[dbo].[TblSPAU'+CONVERT(VARCHAR, @val)+ '] WHERE DateTime between'+CONVERT(VARCHAR(25), @DataStart,121)+ 'and'+CONVERT(VARCHAR(25), @DataStop,121)+';'

END

EXEC sp_sqlexec @sql, N'@DataStart datetime,@DataStop datetime,@val int',  @DataStart, @DataStop, @val

1 Ответов

Рейтинг:
1

CHill60

Вы не объявили @sql вне тела хранимой процедуры. В SP все, что вы делаете, - это устанавливаете переменную и ничего с ней не делаете.

Попробуйте переместить END к после то EXEC

Edit: еще одна мысль - это выглядит как очень плохой дизайн базы данных.

Во-первых, вы, кажется, имеете свой DateTime колонка как тип varchar. Используйте соответствующий тип столбца (например, либо date или datetime).

Избегайте использования зарезервированных слов для имен столбцов но если вы все же не забудьте заключить их в квадратные скобки например[DateTime]

Почему бы не иметь одну таблицу с дополнительным столбцом, который различает различные типы, тогда весь SP становится

select [ID], COL_SPAU_EA FROM [DBRapBreaza].[dbo].[TblSPAU]
 WHERE DateTime between @DataStart and @DataStop 
AND SPAU_TYPE = @val;


РЕДАКТИРОВАТЬ:
Ну, вы утверждаете, что ничего не меняется, но я получаю совершенно другой набор ошибок, когда перемещаю конец в нужное место. Но мои извинения за то, что я подумал ... datetime колонка была варчаром - я неправильно прочитал настройку кода @sql.

Однако я только что понял, что вы используете sp_sqlexec - измените это на sp_executesql - Microsoft рекомендует последнее по сравнению с первым.

Тогда вы получите синтаксические ошибки в своем SQL - вам нужно окружить даты кавычками и включить некоторые пробелы после "Между" и вокруг "и", например
set @sql='select [ID]'+@col2+' FROM [DBRapBreaza].[dbo].[TblSPAU'+CONVERT(VARCHAR, @val)+ '] WHERE DateTime between '''+CONVERT(VARCHAR(25), @DataStart,121)+ ''' and '''+CONVERT(VARCHAR(25), @DataStop,121)+''';'
В ответ на ваш комментарий
Цитата:
Как я уже упоминал, у меня есть 40 таблиц (TblSPAU1...TblSPAU40), которые содержат столбцы, упомянутые выше. DateTime объявляется в БД как datetime. А кто такой SPAU_TYPE в вашем вышеприведенном коде?
Я пытался дать вам альтернативный дизайн базы данных... вместо 40 столов есть только один стол. SPAU_TYPE в моем примере будет иметь значение от 1 до 40 ... таким образом, строки с SPAU_TYPE = 1 будут строками, которые вы сейчас имеете в своем TblSPAU1, те строки с SPAU_TYPE = 2 будут строками, которые вы сейчас имеете в своем TblSPAU2, и т. д. Это гораздо лучший дизайн, с которым значительно проще работать и поддерживать.

Кроме того, это субъективная точка зрения, но большинство опытных программистов избегают префиксов имен таблиц с Tbl или имен столбцов с Col_. Это ничего не добавляет к документации, вызывает дополнительную типизацию и вызывает проблемы в дальнейшем ... например, что делать, если вам нужно заменить то, что изначально было таблицей с представлением? Вам придется проделать большую работу, чтобы изменить TblSPAU на VwSPAU без какой-либо реальной выгоды.


Edit 2 - полный код SP, который я использовал для проверки этого
ALTER PROCEDURE [dbo].[PS_SpauOPompa]

@DataStart datetime,
@DataStop datetime,
@val int
AS
BEGIN
SET NOCOUNT ON;

declare @sql NVARCHAR(max)
declare @col1 varchar
set @col1='ID'
declare @col2 varchar(25) 
set @col2='COL_SPAU'+CONVERT(VARCHAR, @val)+'_EA' 
declare @col3 varchar 
set @col3='DateTime'

set @sql='select [ID],'+@col2+' FROM [dbo].[TblSPAU'+CONVERT(VARCHAR, @val)+ '] WHERE DateTime between '''+CONVERT(VARCHAR(25), @DataStart,121)+ ''' and '''+CONVERT(VARCHAR(25), @DataStop,121)+''';'
PRINT @SQL
EXEC sp_executesql @sql, N'@DataStart datetime,@DataStop datetime,@val int',  @DataStart, @DataStop, @val

END


DrgIonuţ

Я передвинул конец вслед за старпомом, но ничего не изменилось. Как я уже упоминал, у меня есть 40 таблиц (TblSPAU1...TblSPAU40), которые содержат столбцы, упомянутые выше. DateTime объявляется в БД как datetime. А кто такой SPAU_TYPE в вашем вышеприведенном коде? Спасибо за ваш ответ!

CHill60

Я обновил свое решение

DrgIonuţ

Спасибо Вам за ваш ответ! Использование одной таблицы вместо 40 не является решением для моего приложения. Я изменил строку @sql, как вы уже упоминали. Кроме того, Я заменил sp_sqlexec на sp_executesql , но ошибка все равно возникает. Я объявляю @SQL-строку в нужное положение? Или это проблема с тем, как я выполняю процедуру/@sql?

CHill60

Вам нужно поговорить с вашим DBA о таблицах!! :смеяться:
Я вообще не получаю никаких ошибок, так что это должно быть то, как вы выполняете процедуру. Как вы называете эту процедуру?

DrgIonuţ

Я выполняю его вот так:
выполнить [PS_SpauOPompa] '2018-12-12 10:10:10.997', '2018-12-14 14:50:20.680', 4
Если выполнить вот так, то я получу такую ошибку: "максимальный уровень вложенности хранимой процедуры, функции, триггера или представления превышен (предел 32)." Большое спасибо за ваши усилия! :)

CHill60

Сам по себе этот звонок прекрасен. Когда я так называю процедуру, она действительно работает. Через минуту я опубликую полный код этой процедуры в своем решении. Ошибка подразумевает, что вы вызываете SP из другого SP (или триггера), который вызывается из другого SP ...и т. д. Так ли это на самом деле?

DrgIonuţ

Я ее разгадал. Теперь он работает нормально. Еще раз спасибо за ваше время и усилия! Хорошего дня! :)

CHill60

С удовольствием