Инициализируйте Переменную С Выводом Хранимой Процедуры В MS SQL Server

#sql-server #sql-server-2005 #tsql #stored-procedures

Вопрос:

Я создал следующую хранимую процедуру..

 CREATE PROCEDURE [dbo].[UDSPRBHPRIMBUSTYPESTARTUP]
(
  @CODE CHAR(5)
  , @DESC VARCHAR(255) OUTPUT
)
AS
DECLARE @SERVERNAME nvarchar(30)
DECLARE @DBASE nvarchar(30)
DECLARE @SQL nvarchar(2000)

SET @SERVERNAME = 
  Convert(nvarchar,
  (SELECT spData FROM dbSpecificData WHERE spLookup = 'CMSSERVER'))
SET @DBASE = 
  Convert(nvarchar,
  (SELECT spData FROM dbSpecificData WHERE spLookup = 'CMSDBNAME'))

SET @SQL = 
  'SELECT clnt_cat_desc FROM '   @SERVERNAME   
  '.'   @DBASE   '.dbo.hbl_clnt_cat WHERE inactive = ''N''
  AND clnt_cat_code = '''   @CODE   ''''

EXECUTE sp_executeSQL @SQL

RETURN
 

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

Я хочу использовать выходные данные этой процедуры в качестве значения в таблице…

 DECLARE @clid BIGINT
DECLARE @fileid BIGINT
DECLARE @myCode CHAR(5)
DECLARE @myDesc VARCHAR(255)
DECLARE @@tempDesc VARCHAR(255)

SET @clid = 1831400022
SET @fileid = 2072551358
SET @myCode = 
  (SELECT _clientPrimBusinessType FROM udbhextclient WHERE clid = @clid)

SET @myDesc = 
  EXEC UDSPRBHPRIMBUSTYPESTARTUP @CODE = @myCode, @DESC = @@tempDesc OUTPUT
----------------------------------------------------------------------------
SELECT
  a.clid
  , b.fileid
  , c.usrfullname AS ClientPartner
  , e.usrfullname AS ClientFeeEarner
  , @myDesc AS ClientPrimaryBusinessType
FROM 
  dbclient a
    INNER JOIN
  dbFile b
    ON
  a.clid = b.clid
    INNER JOIN
  dbuser c
    ON 
  a.feeusrid = c.usrid
    INNER JOIN
  udbhextclient d
    ON
  a.clid = d.clid
    INNER JOIN
  dbuser e
    ON
  d._ClientFeeEarner = e.usrid
WHERE 
  a.clid = @clid
  AND b.fileid = @fileid
 

Я знаю, что это неверный синтаксис, но вы можете видеть, чего я пытаюсь добиться, не прибегая к временным таблицам, так как это означало бы обслуживание на 30 различных серверах с 3-5 базами данных на каждом.

Сминк — Попробовал ваше решение и получил следующие результаты…

Запуск Решения Smink

Комментарии:

1. Ух ты! Как вы произносите это имя: UDSPRBHPRIMBUSTYPESTARTUP

2. Пакет программного обеспечения содержит множество обновлений. Процесс обновления удалит все, если он не будет соответствовать соглашению об именовании… UD — Определяемый пользователем, SPR — Хранимый процесс, BH — Boodle Hatfield(работодатель),PRIM — Основная ШИНА — Запуск бизнес — типа — Запуск некоторых даже имеет максимальную длину символов 15

3. Завершенный ответ ниже. Посмотри.

4. @Аарон Бертран :Я получил ваше сообщение., Я рассмотрю его.

5. @Аарон Бертран : Большое вам спасибо за внимание. Великий мастер, это изменение повышает читабельность кода. Конечно, это мое мнение. Однако я буду уважать ваше мнение. Я пытаюсь привлечь ваше внимание.

Ответ №1:

Измените строку:

 SET @myDesc = 
  EXEC UDSPRBHPRIMBUSTYPESTARTUP @CODE = @myCode, @DESC = @@tempDesc OUTPUT
 

Для

 EXEC UDSPRBHPRIMBUSTYPESTARTUP @CODE = @myCode, @DESC = @tempDesc OUTPUT
 

И вы пропустили назначение @DESC в хранимой процедуре.

 SET @SQL = 
  'SELECT @DESC = clnt_cat_desc FROM '   @SERVERNAME   
  '.'   @DBASE   '.dbo.hbl_clnt_cat WHERE inactive = ''N''
  AND clnt_cat_code = '''   @CODE   ''''

EXECUTE sp_executeSQL @SQL, N'@DESC varchar(255) output', @DESC output
 

Затем вы должны использовать @tempDesc в следующем выборе:

 SELECT
  a.clid
  , b.fileid
  , c.usrfullname AS ClientPartner
  , e.usrfullname AS ClientFeeEarner
  , @tempDesc AS ClientPrimaryBusinessType
 

Кроме того, ваша хранимая процедура позволяет выполнять SQL-инъекции вокруг:

 SET @SQL = 
  'SELECT clnt_cat_desc 
     FROM '   QUOTENAME(@SERVERNAME)   '.'   QUOTENAME(@DBASE)   '.dbo.hbl_clnt_cat
    WHERE inactive = ''N''
      AND clnt_cat_code = @CODE'

EXECUTE sp_executeSQL @SQL, N'@CODE CHAR(5)', @CODE
 

(Обновление: Исправлены проблемы с внедрением SQL.)

Комментарии:

1. Это возвращает результат, но не помещает значение в приведенную ниже инструкцию <select>.

2. Вы должны использовать @tempDesc в выборе, а не @myDesc. См.Отредактированный ответ.

3. Сминк — я попробовал ваше решение и получил следующие результаты… Пожалуйста, смотрите встроенное изображение.

4. Вы не назначаете @DESC внутри [dbo]. [UDSPRBHPRIMBUSTYPESTARTUP] хранимая процедура.

5. Решение работает, когда вы меняетесь… ВЫПОЛНИТЕ sp_executeSQL @SQL, N’@DESC varchar(255) вывод’, @DESC в… ВЫПОЛНИТЕ sp_executeSQL @SQL, N’Вывод@DESC varchar(255)’, @DESC = ВЫВОД @DESC Не могли бы вы отредактировать свой ответ, чтобы я мог отметить его как принятый? Заранее спасибо.

Ответ №2:

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

Ответ №3:

Вы можете создать функцию (вместо процедуры), которая возвращает таблицу.

 CREATE FUNCTION [dbo].[my_function]
(
   @par2     UNIQUEIDENTIFIER, 
   @par2     UNIQUEIDENTIFIER,
   @par3     UNIQUEIDENTIFIER
)
RETURNS @returntable TABLE 
(
   col1 UNIQUEIDENTIFIER,
   col2 NVARCHAR(50),
   col3 NVARCHAR(50)
)
AS
BEGIN
...
END
 

Ответ №4:

Если вы не хотите касаться своей ПРОЦЕДУРЫ, вы можете создать ФУНКЦИЮ, которая ее обертывает, и использовать эту функцию-оболочку в запросах.