Как я могу присоединиться к хранимой процедуре? - PullRequest
43 голосов
/ 28 мая 2009

У меня есть хранимая процедура, которая не принимает параметров и возвращает два поля. Хранимая процедура суммирует все транзакции, примененные к арендатору, и возвращает баланс и идентификатор арендатора.

Я хочу использовать набор записей, который он возвращает с запросом, и мне нужно объединить его результаты с идентификатором арендатора.

Это мой текущий запрос:

SELECT t.TenantName, t.CarPlateNumber, t.CarColor, t.Sex, t.SSNO, t.Phone, t.Memo,
        u.UnitNumber,
        p.PropertyName
FROM tblTenant t
    LEFT JOIN tblRentalUnit u
    ON t.UnitID = u.ID

    LEFT JOIN tblProperty p
    ON u.PropertyID = p.ID

ORDER BY p.PropertyName, t.CarPlateNumber

Хранимая процедура выглядит так:

SELECT tenant.ID AS TenantID, SUM(ISNULL(trans.Amount,0)) AS TenantBalance FROM tblTenant tenant
    LEFT JOIN tblTransaction trans
    ON tenant.ID = trans.TenantID
    GROUP BY tenant.ID

Я бы тоже хотел добавить к нему баланс из хранимой процедуры.

Как я могу это сделать?

Ответы [ 9 ]

44 голосов
/ 28 мая 2009

вставить результат SP в временную таблицу, затем присоединиться:

CREATE TABLE #Temp (
    TenantID int, 
    TenantBalance int
)

INSERT INTO #Temp
EXEC TheStoredProc

SELECT t.TenantName, t.CarPlateNumber, t.CarColor, t.Sex, t.SSNO, t.Phone, t.Memo,
    u.UnitNumber, p.PropertyName
FROM tblTenant t
INNER JOIN #Temp ON t.TenantID = #Temp.TenantID
...
25 голосов
/ 28 мая 2009

Мне действительно нравится предыдущий ответ (не используйте SP), но если вы по какой-то причине привязаны к самому SP, вы можете использовать его для заполнения временной таблицы, а затем присоединиться к временной таблице. Обратите внимание, что вы будете обходиться там дополнительными затратами, но я думаю, что это единственный способ использовать фактический хранимый процесс.

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

18 голосов
/ 28 мая 2009

Краткий ответ: «Вы не можете». Вам нужно либо использовать подзапрос, либо преобразовать существующую хранимую процедуру в табличную функцию. Создание его как функции будет зависеть от того, насколько «многоразовым» он вам нужен.

9 голосов
/ 28 мая 2009

Ваша хранимая процедура может быть легко использована вместо представления. Тогда вы можете присоединиться к чему-либо еще, что вам нужно.

SQL:

CREATE VIEW vwTenantBalance
AS

 SELECT tenant.ID AS TenantID, SUM(ISNULL(trans.Amount,0)) AS TenantBalance 
 FROM tblTenant tenant
 LEFT JOIN tblTransaction trans
 ON tenant.ID = trans.TenantID
 GROUP BY tenant.ID

Вы можете сделать любое утверждение, как:

SELECT t.TenantName, t.CarPlateNumber, t.CarColor, t.Sex, t.SSNO, t.Phone, 
    t.Memo, u.UnitNumber, p.PropertyName, TenantBalance
FROM tblTenant t
LEFT JOIN tblRentalUnit u
 ON t.UnitID = u.ID
LEFT JOIN tblProperty p
 ON u.PropertyID = p.ID
LEFT JOIN vwTenantBalance v 
 ON t.ID = v.tenantID
ORDER BY p.PropertyName, t.CarPlateNumber
6 голосов
/ 09 августа 2009

Я решил эту проблему, записав функцию вместо процедуры и используя CROSS APPLY в операторе SQL. Это решение работает на SQL 2005 и более поздних версиях.

Гедиминас Букаускас

5 голосов
/ 29 августа 2016

На него уже ответили, лучший способ обойти это - преобразовать хранимую процедуру в функцию SQL или представление.

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

Я отвечу на это, преобразовав вашу хранимую процедуру в функцию SQL, и покажу, как ее использовать в запросе по вашему выбору.

CREATE FUNCTION fnMyFunc()
RETURNS TABLE AS
RETURN 
(
  SELECT tenant.ID AS TenantID, 
       SUM(ISNULL(trans.Amount,0)) AS TenantBalance 
  FROM tblTenant tenant
    LEFT JOIN tblTransaction trans ON tenant.ID = trans.TenantID
  GROUP BY tenant.ID
)

Теперь, чтобы использовать эту функцию в вашем SQL ...

SELECT t.TenantName, 
       t.CarPlateNumber, 
       t.CarColor, 
       t.Sex, 
       t.SSNO, 
       t.Phone, 
       t.Memo,
       u.UnitNumber,
       p.PropertyName
FROM tblTenant t
    LEFT JOIN tblRentalUnit u ON t.UnitID = u.ID
    LEFT JOIN tblProperty p ON u.PropertyID = p.ID
    LEFT JOIN dbo.fnMyFunc() AS a
         ON a.TenantID = t.TenantID
ORDER BY p.PropertyName, t.CarPlateNumber

Если вы хотите передать параметры в вашу функцию из вышеупомянутого SQL, то я рекомендую вам использовать CROSS APPLY или CROSS OUTER APPLY.

Читайте об этом здесь .

Приветствия

2 голосов
/ 28 мая 2009

Я надеюсь, что ваша хранимая процедура не выполняет цикл курсора!

Если нет, возьмите запрос из вашей хранимой процедуры и интегрируйте этот запрос в запрос, который вы отправляете здесь:

SELECT t.TenantName, t.CarPlateNumber, t.CarColor, t.Sex, t.SSNO, t.Phone, t.Memo,
        u.UnitNumber,
        p.PropertyName
        ,dt.TenantBalance
FROM tblTenant t
    LEFT JOIN tblRentalUnit u ON t.UnitID = u.ID
    LEFT JOIN tblProperty   p ON u.PropertyID = p.ID
    LEFT JOIN (SELECT ID, SUM(ISNULL(trans.Amount,0)) AS TenantBalance
                   FROM tblTransaction
                   GROUP BY tenant.ID
              ) dt ON t.ID=dt.ID
ORDER BY p.PropertyName, t.CarPlateNumber

Если вы делаете нечто большее, чем запрос в вашей хранимой процедуре, создайте временную таблицу и выполните хранимую процедуру в этой временной таблице, а затем присоединитесь к ней в своем запросе.

create procedure test_proc
as
  select 1 as x, 2 as y
  union select 3,4 
  union select 5,6 
  union select 7,8 
  union select 9,10
  return 0
go 

create table #testing
(
  value1   int
  ,value2  int
)

INSERT INTO #testing
exec test_proc


select
  *
  FROM #testing
0 голосов
/ 10 октября 2018

Вот вам ужасная идея.

Используйте псевдоним, создайте новый связанный сервер со своего сервера для его собственного псевдонима.

Теперь вы можете сделать:

select a.SomeColumns, b.OtherColumns
from LocalDb.dbo.LocalTable a
inner join (select * from openquery([AliasToThisServer],'
exec LocalDb.dbo.LocalStoredProcedure
') ) b
on a.Id = b.Id
0 голосов
/ 28 мая 2009

Почему бы просто не выполнить вычисления в вашем SQL?

SELECT 
  t.TenantName
  , t.CarPlateNumber
  , t.CarColor
  , t.Sex
  , t.SSNO
  , t.Phone
  , t.Memo
  , u.UnitNumber
  , p.PropertyName
  , trans.TenantBalance
FROM tblTenant t
     LEFT JOIN tblRentalUnit u ON t.UnitID = u.ID
     LEFT JOIN tblProperty p ON u.PropertyID = p.ID
     INNER JOIN (
       SELECT tenant.ID AS TenantID, SUM(ISNULL(trans.Amount,0)) AS TenantBalance 
       FROM tblTenant tenant
            LEFT JOIN tblTransaction trans ON tenant.ID = trans.TenantID
       GROUP BY tenant.ID
     ) trans ON trans.ID = t.ID
ORDER BY 
  p.PropertyName
  , t.CarPlateNumber
...