Невозможно указать индекс или подсказку о блокировке для удаленного источника данных SQL Server 2005 - PullRequest
0 голосов
/ 14 февраля 2012

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

select count(serialno), max(convert(varchar(10),Crtd_DateTime,101))
from tblSBox tsb (nolock)
inner join tblMBox tmb (nolock) on tsb.idMaster = tmb.idMaster
inner join [server_2].fdb.dbo.sns_in_out sio 
      on tsb.serialno = sio.lotsernbr and invtMult='-1' and RefNbr like 'I%'
where tmb.WO=34612

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

SELECT * FROM OpenQuery(server, 'Select * from sometable with (nolock)')

, который работает нормально, но, как вы можете видеть, у меня есть связь между tsb.serialno и sio.lotsernbr, и когда я размещаю все это внутри'', как показано ниже:

select serialno, 
    (SELECT * 
     FROM OpenQuery([server_2], 'select convert(varchar(10), Crtd_DateTime, 101)
                                 from fdb.dbo.sns_in_out sio (nolock) 
                                 where (tsb.serialno = sio.lotsernbr 
                                 and invtMult=''-1'' and RefNbr like ''I%'')')) as crtDate
from tblSBox tsb (nolock)
inner join tblMBox tmb (nolock) on tsb.idMaster = tmb.idMaster
where tmb.WO=34612 

Я получаю эту ошибку:

[Поставщик OLE / DB возвратил сообщение: отложенная подготовка не может быть завершена.]
Сообщение8180, Уровень 16, Состояние 1, Строка 1
Оператор (ы) не может быть подготовлен.
Сообщение 4104, Уровень 16, Состояние 1, Строка 1
Может быть составной идентификатор "tsb.serialno"не быть связанным.

Есть идеи, как этого добиться?

1 Ответ

1 голос
/ 14 февраля 2012

Если вы хотите выполнять запросы с (NOLOCK) на удаленном сервере, создайте хранимую процедуру или представление на удаленном сервере и примените подсказку блокировки там.

Если у вас нет доступа к удаленному серверу, вы можете сначала получить данные, выполнив что-то вроде этого через связанный сервер (я предполагаю, что ваш связанный сервер называется server_2):

CREATE TABLE #loc (lotsernbr INT, dt DATETIME);

INSERT #loc
EXEC [server_2].fdb..sp_executesql 'SELECT lotsernbr, Crt_DateTime
    FROM dbo.sns_in_out WITH (NOLOCK)
    WHERE invtMult=''-1'' AND RefNbr LIKE ''I%'';';

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- much better than nolock on every table

SELECT tsb.serialno, crtDate = CONVERT(CHAR(10), loc.dt, 101)
    FROM tblSBox AS tsb 
    INNER JOIN #loc AS loc
    ON tsb.serialno = loc.lotsernbr
    INNER JOIN tblMBox AS tmb
    ON tsb.idMaster = tmb.idMaster
    WHERE tmb.WO = 34612;

Теперь вы можете присоединиться к локальной таблице #temp. Разница может быть незначительной, но она может быть значительной. Если это приводит к большому количеству строк, а вам нужно только несколько, возможно, вы захотите сделать это немного по-другому: динамически создайте список IN и передайте его на другой сервер, например,

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'';

SELECT @sql = @sql + ',' + CONVERT(VARCHAR(12), serialno)
    FROM tblSBox AS tsb
    INNER JOIN tblMBox AS tmb
    ON tsb.idMaster = tmb.idMaster
    WHERE tmb.WO = 34612
    GROUP BY serialno; -- to avoid dupes

SET @sql = N'SELECT serialno = lotsernbr, crtDate = CONVERT(CHAR(10), Crt_Datetime, 101)
    FROM fdb.dbo.sns_in_out WITH (NOLOCK)
    WHERE lotsernbr IN (' + STUFF(@sql, 1, 1, N'') + ');'

-- now you don't need the join, since you are only outputting 
-- the two columns:
EXEC [server_2].fdb..sp_executesql @sql;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...