Компонент Service Broker: как определить, что сценарий выполняется на требуемой машине?

Мои сценарии SQL генерируются из шаблонов. Они содержат IP-адрес. Их может быть много, и оператор по ошибке может выполнить неверный скрипт. Как скрипт может проверить, был ли он запущен на правильной машине? (В противном случае я хотел бы распечатать сообщение и выйти.)

Это вообще возможно?

Спасибо Петр


person pepr    schedule 03.11.2012    source источник
comment
Вы это нашли? stackoverflow.com/questions/142142 /   -  person bummi    schedule 04.11.2012
comment
@bummi: Мне это не понравилось из-за ipconfig в наиболее популярном ответе. Но если вы напишете ответ со ссылкой на stackoverflow.com/a/9622810/1346705, я проголосую за него. Во всяком случае, это был скорее побочный вопрос. Я собираюсь обновить вопрос.   -  person pepr    schedule 05.11.2012


Ответы (4)


Обновленный ответ

Вот сценарий, который я нашел в http://weblogs.sqlteam.com/peterl/archive/2008/07/16/How-to-get-IP-address.aspx с некоторыми изменениями, которые лучше соответствуют вашим потребностям:

DECLARE @TargetIpAddress varchar(15);
SET @TargetIpAddress = '127.0.0.1'; --<== The IP address of the server you want.

DECLARE @Interfaces TABLE
(
    RowID int IDENTITY(0, 1)
   ,Interface char(38)
   ,IP varchar(15)
);

INSERT @Interfaces ( Interface )
  EXEC master..xp_regenumkeys N'HKEY_LOCAL_MACHINE',
       N'System\CurrentControlSet\Services\TcpIP\Parameters\Interfaces';

DECLARE @RowID int
       ,@IP varchar(15)
       ,@Key nvarchar(200);

SELECT @RowID = MAX(RowID)
  FROM @Interfaces;

WHILE @RowID >= 0
BEGIN
    SELECT @Key = N'System\CurrentControlSet\Services\TcpIP\Parameters\Interfaces\' + Interface
     FROM @Interfaces
    WHERE RowID = @RowID;

    EXEC master..xp_regread N'HKEY_LOCAL_MACHINE', @Key, N'DhcpIPAddress', @IP OUTPUT;

    IF @IP <> '0.0.0.0'
    UPDATE @Interfaces
       SET IP = @IP
     WHERE RowID = @RowID;

    SET @RowID = @RowID - 1;
END;

IF NOT EXISTS (SELECT IP FROM @Interfaces WHERE IP = @TargetIpAddress)
BEGIN
    DECLARE @ErrorMessage varchar(2000);
    SET @ErrorMessage  = 'This is not the correct server. This server does not have an IP address of %s.';
    SET @TargetIpAddress = ISNULL(@TargetIpAddress, 'NULL');
    RAISERROR(@ErrorMessage, 16, 1, @TargetIpAddress);
END

-- The rest of the script...

Оригинальный ответ

Похоже, что с использованием имени Server \ Instance вместо IP-адреса будет легче работать и будет меньше шансов сломаться, если серверу (-ам) будут назначены другие IP-адреса позднее.

-- You can get the instance name like this:
SELECT @@SERVERNAME +'\'+ @@SERVICENAME AS 'Instance';

-- Although, you might prefer this instead:
SELECT CAST(SERVERPROPERTY('MachineName') AS nvarchar(128))
      +COALESCE('\'+CAST(SERVERPROPERTY('InstanceName') AS nvarchar(128)), '');

-- NetBIOS name of the local computer on which the instance of SQL Server
-- is currently running.
-- If the instance of SQL Server is in a failover cluster and you want to obtain
-- the name of the failover clustered instance, use the MachineName property. 
SELECT SERVERPROPERTY('ComputerNamePhysicalNetBIOS');

Подробную информацию о функции СЕРВЕРСВОЙСТВА можно найти на странице MSDN: SERVERPROPERTY (Transact-SQL) < / а>. Хотя эта функция не предоставляет никакого способа получить IP-адрес сервера / экземпляра - нет встроенной функции, предоставляющей эту информацию.

person Alexander    schedule 04.11.2012
comment
+1 Я предпочитаю IP по разным причинам, но и ваш ответ мне важен. Спасибо. - person pepr; 05.11.2012
comment
Вы можете обернуть сценарий, который я включил в свой обновленный ответ, в хранимую процедуру, если хотите также инкапсулировать код. - person Alexander; 05.11.2012

Create Procedure P_GetIPAddresses (@IPS varchar(4000) out)
as
begin
Select @IPS=''
Create TABLE #temp (Line varchar(200))
Insert #temp exec master..xp_cmdshell 'ipconfig'
Select @IPS = @IPS + Coalesce(RTRIM(Replace(SubString(Line,1,CharIndex(':',line)-1)  ,'.','')) + SubString(Line,CharIndex(':',line) ,200),'')
from #temp
where upper (Line) like '%ADRESS%'
--SELECT * from #tmp --DEBUG
DROP TABLE #temp

end 

Использование, если xp_cmdshell отключен, анализ адресов зависит от вас ...

EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO


Declare @IPS Varchar(4000)

exec P_GetIPAddresses @IPS out
Select  @IPS

EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 0
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO
person bummi    schedule 05.11.2012
comment
Что ж ... Мне еще ipconfig решение не нравится. Как вы думаете, он лучше, чем stackoverflow.com/a/9622810/1346705? - person pepr; 05.11.2012
comment
кажется знакомым ... тебе не нравится xp_cmdshel или ipconfig? - person bummi; 05.11.2012
comment
Ну и то, и другое. Я считаю, что мне не следует использовать внешние инструменты, если можно получить ту же информацию с помощью встроенных механизмов. Есть ли у вас опыт работы с sys.dm_exec_connections, упомянутым chris.leonard? Я попробовал его решение (см. Ссылку), и оно работает. Однако я не знаю, как это работает и правильно ли это. - person pepr; 05.11.2012
comment
Выберите local_net_address из sys.dm_exec_connections, где session_ID = @@ SPID работает нормально, если вы подключаетесь к удаленному серверу, если вы запускаете скрипт на локальном компьютере, он будет NULL - person bummi; 05.11.2012

Я мог бы предоставить xp_GetIP.dll, но протестировал его только с 32-разрядной версией SQL-Server 2005, которую вы могли зарегистрировать через

EXEC sp_addextendedproc xp_GetIP, 'C: \ temp \ xpGetIP.dll'

Звонок будет

Declare @IP varchar(100)

exec xp_GetIP @IP output
print @IP

только вывод: 192.168.69.69

РЕДАКТИРОВАТЬ: Работа с SQL-Server 2008 R2 64-битной als 64-битной DLL

person bummi    schedule 05.11.2012

Извините за репост, но меня раздражает отсутствие возможности доступа к системным данным внутри SQL-Server, я решил написать расширенную хранимую процедуру как мост к WMI.

Загрузите http://bummisoft.de/download/XP_WMI.zip.

звонок будет:

exec xp_wmiv3 'Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE'

DLL доступна для 32-битных и 64-битных SQLServers и бесплатна для некоммерческого использования.

Установка:

EXEC sp_addextendedproc xp_wmiv3, '<Your Path>\XP_WMIV3_DLL.dll'

eg: EXEC sp_addextendedproc xp_wmiv3, 'C:\DLLs\XP_WMIV3_DLL.dll'

Удаление

EXEC sp_dropextendedproc xp_wmiv3

использование

e.g.

exec xp_wmiv3 'SELECT * FROM Win32_Volume'
exec xp_wmiv3 'SELECT * FROM CIM_Userdevice where Name like "%HID%"'



create table #tmp(
    Domain varchar(255),
    Name varchar(255),Sid varchar(255)
)
insert into #tmp 
exec xp_wmiV2 'SELECT Domain, SID, Name FROM Win32_UserAccount where Status = "OK"'
select * from #tmp
drop table #tmp

В настоящее время протестировано под SQL-Server 2005 и SQL-Server 2008.

person bummi    schedule 09.11.2012