I'm upgrading our reporting server from 2008 R2 32-bit to 2014 32-bit.
We have linked servers that are excel files. These are .xls files (although the problem persists when they are updated to .xlsm). The connects work fine (select & insert into); however, when we run a stored procedure to create a new tab in the excel file.
USE [SupplementaryReports]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[spExecute_ADODB_SQL]
#DDL VARCHAR(8000),
#DataSource VARCHAR(500),
#Worksheet VARCHAR(200)=NULL,
#ConnectionString VARCHAR(255) = 'Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=%DataSource;
Extended Properties=Excel 12.0'
AS
DECLARE
#objExcel INT,
#hr INT,
#command VARCHAR(255),
#strErrorMessage VARCHAR(255),
#objErrorObject INT,
#objConnection INT,
#bucket INT
SELECT #ConnectionString =REPLACE (#ConnectionString, '%DataSource', #DataSource)
IF #Worksheet IS NOT NULL
SELECT #DDL=REPLACE(#DDL,'%worksheet',#Worksheet)
SELECT #strErrorMessage='Making ADODB connection ',
#objErrorObject=NULL
EXEC #hr=sp_OACreate 'ADODB.Connection', #objconnection OUT
IF #hr=0
SELECT #strErrorMessage='Assigning ConnectionString property "'
+ #ConnectionString + '"',
#objErrorObject=#objconnection
IF #hr=0 EXEC #hr=sp_OASetProperty #objconnection, 'ConnectionString', #ConnectionString
IF #hr=0 SELECT #strErrorMessage ='Opening Connection to XLS, for file Create or Append'
IF #hr=0 EXEC #hr=sp_OAMethod #objconnection, 'Open'
IF #hr=0 SELECT #strErrorMessage ='Executing DDL "'+#DDL+'"'
IF #hr=0 EXEC #hr=sp_OAMethod #objconnection, 'Execute',
#Bucket out , #DDL
IF #hr<>0
BEGIN
DECLARE
#Source VARCHAR(255),
#Description VARCHAR(255),
#Helpfile VARCHAR(255),
#HelpID INT
EXECUTE sp_OAGetErrorInfo #objErrorObject, #source output,
#Description output,#Helpfile output,#HelpID output
SELECT #strErrorMessage='Error whilst '
+COALESCE(#strErrorMessage,'doing something')+', '
+COALESCE(#Description,'')
RAISERROR (#strErrorMessage,16,1)
END
EXEC #hr=sp_OADestroy #objconnection
GO
I get the following error
Msg 15281, Level 16, State 1, Procedure sp_OACreate, Line 116
SQL Server blocked access to procedure 'sys.sp_OACreate' of component 'Ole Automation Procedures' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'Ole Automation Procedures' by using sp_configure. For more information about enabling 'Ole Automation Procedures', search for 'Ole Automation Procedures' in SQL Server Books Online.
Msg 15281, Level 16, State 1, Procedure sp_OADestroy, Line 116
SQL Server blocked access to procedure 'sys.sp_OADestroy' of component 'Ole Automation Procedures' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'Ole Automation Procedures' by using sp_configure. For more information about enabling 'Ole Automation Procedures', search for 'Ole Automation Procedures' in SQL Server Books Online.
This error often means that ad hoc distribtued queries are not enough. But they are (both 'show advanced options' and 'ad hoc distributed queries' are set to 1). We also have the provider Microsoft.ACE.OLEDB.12.0 with allow in process and dynamic paramteres enabled.
The excel files work perfectly with 2008 R2. The code itself hasn't been changed. All that's changed is upgrading to 2014. Does anyone have any suggestions? You know... besides not using SQL to connect to excel files since we don't have the resources to change that.
Much obliged!
The most likely answer is Ole Automation Procedures is not turned on. You can check by running:
EXEC sp_configure 'Ole Automation Procedures';
This will return something along the lines of:
name minimum maximum config_value run_value
Ole Automation Procedures 0 1 0 0
If the config_value is 0 you need to enable it.
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
Source.
Related
I have just set up a new SQL Server instance on a new server and moved our application to use the new server. So I've had to turn SQL Agent off on the old server - turning it on would start the scheduler and start sending out emails and running things that shouldn't be run any more.
However, I need to take a close look at a SQL Agent Job on the old server, and ideally reverse-engineer the code to recreate it so I can modify it and apply it to the new server.
How do I generate the code for that Job on the old server without turning SQL Agent on?
Thanks
Even if SQL server agent is not running, you can see how jobs and schedules were set up by viewing the following system DMVs.
msdb.dbo.sysjobs_view
msdb.dbo.sysjobs
msdb.dbo.sysjobschedules
msdb.dbo.sysschedules
I use preset scripts to create all my jobs and schedules independent of the server. Here is a sample script to create the recycle log job. You can modify this or use any piece of this as you see fit.
DECLARE #sql nvarchar(max)
BEGIN TRY
IF EXISTS (SELECT job_id
FROM msdb.dbo.sysjobs_view
WHERE name = N'Cycle SQL log')
EXEC msdb.dbo.sp_delete_job #job_name=N'Cycle SQL log'
, #delete_unused_schedule=1
EXEC msdb.dbo.sp_add_job
#job_name = N'Cycle SQL log',
#description = N'This job forces SQL to start a new error log (In the Managment node of SSMS)',
#owner_login_name = N'your_sql_login' ;
EXEC msdb.dbo.sp_add_jobstep
#job_name = N'Cycle SQL log',
#step_name = N'sp_cycle_errorlog',
#subsystem = N'TSQL',
#command = N'exec sp_cycle_errorlog' --put your executable code here
--These next two lines set the target server to local, so that the job can be modified if necessary
SET #sql = 'EXEC msdb.dbo.sp_add_jobserver #job_name=N''Cycle SQL Log'', #server_name = N''' + ##SERVERNAME + ''''
EXEC sys.sp_executesql #stmt = #sql
END TRY
BEGIN CATCH
PRINT 'Uh-oh. Something bad happened when creating the Cycle SQL Log job. See the following error.'
PRINT CAST(ERROR_MESSAGE() AS NVARCHAR(1000))
END CATCH
You can use use code to automate the addition of schedules based on values you pull from the DMVs listed above.
I recently installed SQL Server 2017 Express and localdb (general availablity). While attempting to install the tSQLt framework I've discovered a new security feature implemented in SQL Server 2017: the "clr strict security" option. This new security feature seems to prevent the creation of the tSQLtCLR assembly.
The SQL error message states:
CREATE or ALTER ASSEMBLY for assembly 'tSQLtCLR' with the SAFE or
EXTERNAL_ACCESS option failed because the 'clr strict security' option
of sp_configure is set to 1. Microsoft recommends that you sign the
assembly with a certificate or asymmetric key that has a corresponding
login with UNSAFE ASSEMBLY permission. Alternatively, you can trust
the assembly using sp_add_trusted_assembly.
I've read Microsoft's technical documentation related to the sp_add_trusted_assembly procedure, but it seems to assume that you were able to successfully create the assembly. How would one code the tSQLtCLR assembly to be listed as "trusted" if you can't get it created in the first place?
SQL Server 2017 introduces a new server-level configuration option named "CLR strict security", and it is enabled by default. This option requires that ALL Assemblies, even SAFE ones, be signed with a certificate or strong name key, and that the Certificate or Asymmetric Key used to do that signing is loaded into [master], and has a Login created from it, and that Login has been granted the UNSAFE ASSEMBLY permission.
Due to SAFE Assemblies now needing to have the signature-based Login in place before being loaded via CREATE ASSEMBLY, it is no longer possible to have an empty, signed Assembly that gets loaded into [master] via CREATE ASSEMBLY ... FROM 0x... WITH PERMISSION_SET = SAFE;.
Now, there are only two ways to create objects usable to set up SQLCLR security from a VARBINARY literal or variable (i.e. not from an external file):
CREATE ASSEMBLY ... FROM 0x...;
CREATE CERTIFICATE ... FROM BINARY = 0x...;
Option #1 is no longer an option, at least not by itself. Option 2 is fine, but was never preferred due Certificates not being fully integrated into the Visual Studio / MSBuild build process.
Fortunately, there are two ways to fix this as discussed in the following two blog posts of mine:
SQLCLR vs. SQL Server 2017, Part 2: “CLR strict security” – Solution 1 — more steps than Part 3, Solution 2 (below), but a good fit for existing projects as it requires almost no changes to the existing solution or even deployment process (and in fact, this is effectively the route that I went for my SQL# project as all it did was add 3 simple steps to the beginning of the installation script)
SQLCLR vs. SQL Server 2017, Part 3: “CLR strict security” – Solution 2
HOWEVER,
that just answers the question of "why" you are in the situation that you are currently in. To fix that situation, assuming that you likely aren't going to update the tSQLt build process to include a Certificate, then you can do a simple one-time fix of:
ALTER DATABASE [master] SET TRUSTWORTHY ON;
EXEC tSQLt.InstallExternalAccessKey;
EXEC master.sys.sp_executesql N'GRANT UNSAFE ASSEMBLY TO [tSQLtExternalAccessKey];';
ALTER DATABASE [master] SET TRUSTWORTHY OFF;
The GRANT UNSAFE ASSEMBLY is there due to the tSQLt.InstallExternalAccessKey Stored Procedure only granting EXTERNAL ACCESS ASSEMBLY to the Login, which used to be fine, but now is not enough.
Of course, you won't be able to load the tSQLt Assemblies until those 4 steps are done, so if the process is to load everything first and that is failing, then you will need to do:
EXEC sp_configure 'clr strict security', 0; RECONFIGURE;
-- Install tSQLt ...
EXEC tSQLt.InstallExternalAccessKey;
EXEC master.sys.sp_executesql N'GRANT UNSAFE ASSEMBLY TO [tSQLtExternalAccessKey];';
EXEC sp_configure 'clr strict security', 1; RECONFIGURE;
I created an issue in the tSQLt GitHub repository with the steps require to incorporate the ideal fix into the source files: https://github.com/tSQLt-org/tSQLt/issues/25
PLEASE NOTE
that none of these possible solutions includes using the new "Trusted Assemblies" feature. That feature should never, ever be used by anyone for any reason (outside of sheer curiosity and testing). The reasons for avoiding it are detailed in several blog posts (currently 3 and more on the way) starting with:
SQLCLR vs. SQL Server 2017, Part 4: “Trusted Assemblies” – The Disappointment
The tSQLt assembly is signed already. For now, you can create the assembly in master, create a certificate from it, drop the assembly again and then take the necessary steps with that certificate.
I'm working on getting the required step to install tSQLt on 2017 automated.
This worked for me:
declare
#hash binary(64)
,#description nvarchar(4000)
select
#hash = HASHBYTES('SHA2_512', af.content)
, #description = a.clr_name
FROM sys.assemblies a
JOIN sys.assembly_files af
ON a.assembly_id = af.assembly_id
WHERE a.is_user_defined = 1
and a.name = 'tSQLtCLR'
EXEC sys.sp_add_trusted_assembly
#hash
,#description
You can use this script on master and then try to run tSQLt framework script query:
USE master
GO
IF OBJECT_ID('tempdb..#Private_GetAssemblyKeyBytes') IS NOT NULL DROP PROCEDURE #Private_GetAssemblyKeyBytes;
GO
CREATE PROCEDURE #Private_GetAssemblyKeyBytes
#AssemblyKeyBytes VARBINARY(MAX) = NULL OUTPUT,
#AssemblyKeyThumbPrint VARBINARY(MAX) = NULL OUTPUT
AS
SELECT #AssemblyKeyBytes =
0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062+
0x652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C010300BB91FD5F0000000000000000E00022200B013000000A0000000600000000000042280000002000000040000000000010002000000002000004000000000000+
0x0004000000000000000080000000020000919C0000030040850000100000100000000010000010000000000000100000000000000000000000F02700004F00000000400000A003000000000000000000000000000000000000006000000C000000B82600+
0x001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E746578740000004808000000200000000A0000000200+
0x00000000000000000000000000200000602E72737263000000A00300000040000000040000000C0000000000000000000000000000400000402E72656C6F6300000C00000000600000000200000010000000000000000000000000000040000042000000+
0x000000000000000000000000002428000000000000480000000200050058200000E005000009000000000000000000000000000000382600008000000000000000000000000000000000000000000000000000000000000000000000001E02280F00000A+
0x2A42534A4201000100000000000C00000076322E302E35303732370000000005006C000000A8010000237E0000140200002C02000023537472696E67730000000040040000040000002355530044040000100000002347554944000000540400008C0100+
0x0023426C6F620000000000000002000001471400000900000000FA013300160000010000001000000002000000010000000F0000000E0000000100000001000000000078010100000000000600ED00DE0106005A01DE0106002100AC010F00FE01000006+
0x00490094010600D00094010600B100940106004101940106000D01940106002601940106007900940106003500BF0106001300BF0106009400940106006000940106000D028D010000000001000000000001000100000010002502140241000100010050+
0x20000000008618A601060001000900A60101001100A60106001900A6010A002900A60110003100A60110003900A60110004100A60110004900A60110005100A60110005900A60110006100A60115006900A60110007100A60110007900A60110008100A6+
0x0106002E000B00C5002E001300CE002E001B00ED002E002300F6002E002B000C012E0033000C012E003B000C012E00430012012E004B001D012E0053000C012E005B000C012E00630035012E006B005F012E0073006C0104800000010000000000000001+
0x0000002300140200000200000000000000000000001A000A000000000000000000003C4D6F64756C653E006D73636F726C696200477569644174747269627574650044656275676761626C6541747472696275746500436F6D56697369626C6541747472+
0x696275746500417373656D626C795469746C6541747472696275746500417373656D626C794B65794E616D6541747472696275746500417373656D626C7954726164656D61726B41747472696275746500417373656D626C7946696C6556657273696F6E+
0x41747472696275746500417373656D626C79436F6E66696775726174696F6E41747472696275746500417373656D626C794465736372697074696F6E41747472696275746500436F6D70696C6174696F6E52656C61786174696F6E734174747269627574+
0x6500417373656D626C7950726F6475637441747472696275746500417373656D626C79436F7079726967687441747472696275746500417373656D626C79436F6D70616E794174747269627574650052756E74696D65436F6D7061746962696C69747941+
0x7474726962757465007453514C74417373656D626C794B65792E646C6C0053797374656D0053797374656D2E5265666C656374696F6E002E63746F720053797374656D2E446961676E6F73746963730053797374656D2E52756E74696D652E496E746572+
0x6F7053657276696365730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573004F626A656374007453514C74417373656D626C794B657900656D7074790000000000009C98AF3349A76E+
0x4AA6D306AB985BCF8E00042001010803200001052001011111042001010E042001010208B77A5C561934E08980A00024000004800000940000000602000000240000525341310004000001000100B9AF416AD8DFEDEC08A5652FA257F1242BF4ED60EF5A+
0x7B84A429604D62C919C5663A9C7710A7C5DF9953B69EC89FCE85D71E051140B273F4C9BF890A2BC19C48F22D7B1F1D739F90EEBC5729555F7F8B63ED088BBB083B336F7E38B92D44CFE1C842F09632B85114772FF2122BC638C78D497C4E88C2D656C166+
0x050D6E1EF3940801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F777301080100020000000000150100107453514C74417373656D626C794B657900000501000000000A0100057453514C74000017010012436F+
0x7079726967687420C2A920203230313900002901002430333536303035622D373166642D346466332D383530322D32376336613630366539653800000C010007312E302E302E3000001D0100187453514C745F4F6666696369616C5369676E696E674B65+
0x7900000000E73936ABF16E67A4775423AE67F541BFE077E40098D90CEE90D33A631CE7C62B60228445A1C9B8A698B13317C65FD100A55706470458F0CE8C8E8CF2F30B457604C6E5F07A6862B1B45AB75E470E9F5D20E7596164413276227809F5BA14FC+
0x8A08DEEB63878D480DAE9D11907249CE1C6F58C9E69E925F071F552DEE436ADA0400000000BB91FD5F00000000020000001C010000D4260000D408000052534453D827CA8B9C7A5A4597EBB065786433D601000000443A5C615C315C735C7453514C7443+
0x4C525C7453514C74417373656D626C794B65795C6F626A5C437275697365436F6E74726F6C5C7453514C74417373656D626C794B65792E706462000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001828000000000000000000003228000000200000000000000000000000000000000000000000000024280000000000000000000000005F+
0x436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF250020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001001000000018000080000000+
0x00000000000000000000000100010000003000008000000000000000000000000000000100000000004800000058400000440300000000000000000000440334000000560053005F00560045005200530049004F004E005F0049004E0046004F00000000+
0x00BD04EFFE00000100000001000000000000000100000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073+
0x006C006100740069006F006E00000000000000B004A4020000010053007400720069006E006700460069006C00650049006E0066006F0000008002000001003000300030003000300034006200300000001A000100010043006F006D006D0065006E0074+
0x00730000000000000022000100010043006F006D00700061006E0079004E0061006D00650000000000000000004A0011000100460069006C0065004400650073006300720069007000740069006F006E00000000007400530051004C0074004100730073+
0x0065006D0062006C0079004B006500790000000000300008000100460069006C006500560065007200730069006F006E000000000031002E0030002E0030002E00300000004A001500010049006E007400650072006E0061006C004E0061006D00650000+
0x007400530051004C00740041007300730065006D0062006C0079004B00650079002E0064006C006C00000000004800120001004C006500670061006C0043006F007000790072006900670068007400000043006F00700079007200690067006800740020+
0x00A90020002000320030003100390000002A00010001004C006500670061006C00540072006100640065006D00610072006B00730000000000000000005200150001004F0072006900670069006E0061006C00460069006C0065006E0061006D00650000+
0x007400530051004C00740041007300730065006D0062006C0079004B00650079002E0064006C006C00000000002C0006000100500072006F0064007500630074004E0061006D006500000000007400530051004C0074000000340008000100500072006F+
0x006400750063007400560065007200730069006F006E00000031002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000031002E0030002E0030002E0030000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000+
0x000C0000004438000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+
0x000000000000000000
,#AssemblyKeyThumbPrint = 0xE8FFF6F136D7B53E ;
GO
IF OBJECT_ID('tempdb..#Private_EnableCLR') IS NOT NULL DROP PROCEDURE #Private_EnableCLR;
GO
CREATE PROCEDURE #Private_EnableCLR
AS
BEGIN
EXEC master.sys.sp_configure #configname='clr enabled', #configvalue = 1;
RECONFIGURE;
END;
GO
IF OBJECT_ID('tempdb..#Private_GetSQLProductMajorVersion') IS NOT NULL DROP PROCEDURE #Private_GetSQLProductMajorVersion;
GO
CREATE PROCEDURE #Private_GetSQLProductMajorVersion
AS
RETURN CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(MAX)),4) AS INT);
GO
DECLARE #Version INT;
EXEC #Version = #Private_GetSQLProductMajorVersion;
PRINT #Version;
GO
IF OBJECT_ID('tempdb..#RemoveAssemblyKey') IS NOT NULL DROP PROCEDURE #RemoveAssemblyKey;
GO
CREATE PROCEDURE #RemoveAssemblyKey
AS
BEGIN
IF(NOT EXISTS(SELECT * FROM sys.fn_my_permissions(NULL,'server') AS FMP WHERE FMP.permission_name = 'CONTROL SERVER'))
BEGIN
RAISERROR('Only principals with CONTROL SERVER permission can execute this procedure.',16,10);
RETURN -1;
END;
DECLARE #master_sys_sp_executesql NVARCHAR(MAX); SET #master_sys_sp_executesql = 'master.sys.sp_executesql';
DECLARE #ProductMajorVersion INT;
EXEC #ProductMajorVersion = #Private_GetSQLProductMajorVersion;
IF SUSER_ID('tSQLtAssemblyKey') IS NOT NULL DROP LOGIN tSQLtAssemblyKey;
EXEC #master_sys_sp_executesql N'IF ASYMKEY_ID(''tSQLtAssemblyKey'') IS NOT NULL DROP ASYMMETRIC KEY tSQLtAssemblyKey;';
EXEC #master_sys_sp_executesql N'IF EXISTS(SELECT * FROM sys.assemblies WHERE name = ''tSQLtAssemblyKey'') DROP ASSEMBLY tSQLtAssemblyKey;';
DECLARE #cmd NVARCHAR(MAX);
IF(#ProductMajorVersion>=14)
BEGIN
DECLARE #TrustedHash NVARCHAR(MAX);
DECLARE #AssemblyKeyBytes VARBINARY(MAX);
EXEC #Private_GetAssemblyKeyBytes #AssemblyKeyBytes = #AssemblyKeyBytes OUT;
SELECT #TrustedHash = CONVERT(NVARCHAR(MAX),HASHBYTES('SHA2_512',#AssemblyKeyBytes),1);
SELECT #cmd =
'IF EXISTS(SELECT 1 FROM sys.trusted_assemblies WHERE hash = ' + #TrustedHash +' AND description = ''tSQLt Ephemeral'')'+
'EXEC sys.sp_drop_trusted_assembly #hash = ' + #TrustedHash + ';';
EXEC master.sys.sp_executesql #cmd;
END;
END;
GO
IF OBJECT_ID('tempdb..#InstallAssemblyKey') IS NOT NULL DROP PROCEDURE #InstallAssemblyKey;
GO
CREATE PROCEDURE #InstallAssemblyKey
AS
BEGIN
IF(NOT EXISTS(SELECT * FROM sys.fn_my_permissions(NULL,'server') AS FMP WHERE FMP.permission_name = 'CONTROL SERVER'))
BEGIN
RAISERROR('Only principals with CONTROL SERVER permission can execute this procedure.',16,10);
RETURN -1;
END;
DECLARE #cmd NVARCHAR(MAX);
DECLARE #cmd2 NVARCHAR(MAX);
DECLARE #master_sys_sp_executesql NVARCHAR(MAX); SET #master_sys_sp_executesql = 'master.sys.sp_executesql';
DECLARE #ProductMajorVersion INT;
EXEC #ProductMajorVersion = #Private_GetSQLProductMajorVersion;
DECLARE #AssemblyKeyBytes VARBINARY(MAX),
#AssemblyKeyThumbPrint VARBINARY(MAX);
EXEC #Private_GetAssemblyKeyBytes #AssemblyKeyBytes OUT, #AssemblyKeyThumbPrint OUT;
SET #cmd = 'IF EXISTS(SELECT * FROM sys.assemblies WHERE name = ''tSQLtAssemblyKey'') DROP ASSEMBLY tSQLtAssemblyKey;';
EXEC #master_sys_sp_executesql #cmd;
SET #cmd2 = 'SELECT #cmd = ''DROP ASSEMBLY ''+QUOTENAME(A.name)+'';'''+
' FROM master.sys.assemblies AS A'+
' WHERE A.clr_name LIKE ''tsqltassemblykey, %'';';
EXEC sys.sp_executesql #cmd2,N'#cmd NVARCHAR(MAX) OUTPUT',#cmd OUT;
EXEC #master_sys_sp_executesql #cmd;
DECLARE #Hash VARBINARY(64) = NULL;
IF(#ProductMajorVersion>=14)
BEGIN
SELECT #Hash = HASHBYTES('SHA2_512',#AssemblyKeyBytes);
SELECT #cmd =
'IF NOT EXISTS (SELECT * FROM sys.trusted_assemblies WHERE [hash] = #Hash)'+
'BEGIN'+
' EXEC sys.sp_add_trusted_assembly #hash = #Hash, #description = N''tSQLt Ephemeral'';'+
'END ELSE BEGIN'+
' SELECT #Hash = NULL FROM sys.trusted_assemblies WHERE [hash] = #Hash AND description <> ''tSQLt Ephemeral'';'+
'END;';
EXEC #master_sys_sp_executesql #cmd, N'#Hash VARBINARY(64) OUTPUT',#Hash OUT;
END;
SELECT #cmd =
'CREATE ASSEMBLY tSQLtAssemblyKey AUTHORIZATION dbo FROM ' +
CONVERT(NVARCHAR(MAX),#AssemblyKeyBytes,1) +
' WITH PERMISSION_SET = SAFE;'
EXEC #master_sys_sp_executesql #cmd;
IF SUSER_ID('tSQLtAssemblyKey') IS NOT NULL DROP LOGIN tSQLtAssemblyKey;
SET #cmd = N'IF ASYMKEY_ID(''tSQLtAssemblyKey'') IS NOT NULL DROP ASYMMETRIC KEY tSQLtAssemblyKey;';
EXEC #master_sys_sp_executesql #cmd;
SET #cmd2 = 'SELECT #cmd = ISNULL(''DROP LOGIN ''+QUOTENAME(SP.name)+'';'','''')+''DROP ASYMMETRIC KEY '' + QUOTENAME(AK.name) + '';'''+
' FROM master.sys.asymmetric_keys AS AK'+
' LEFT JOIN master.sys.server_principals AS SP'+
' ON AK.sid = SP.sid'+
' WHERE AK.thumbprint = #AssemblyKeyThumbPrint;';
EXEC sys.sp_executesql #cmd2,N'#cmd NVARCHAR(MAX) OUTPUT, #AssemblyKeyThumbPrint VARBINARY(MAX)',#cmd OUT, #AssemblyKeyThumbPrint;
EXEC #master_sys_sp_executesql #cmd;
SET #cmd = 'CREATE ASYMMETRIC KEY tSQLtAssemblyKey FROM ASSEMBLY tSQLtAssemblyKey;';
EXEC #master_sys_sp_executesql #cmd;
SET #cmd = 'CREATE LOGIN tSQLtAssemblyKey FROM ASYMMETRIC KEY tSQLtAssemblyKey;';
EXEC #master_sys_sp_executesql #cmd;
SET #cmd = 'DROP ASSEMBLY tSQLtAssemblyKey;';
EXEC #master_sys_sp_executesql #cmd;
IF(#Hash IS NOT NULL)
BEGIN
SELECT #cmd = 'EXEC sys.sp_drop_trusted_assembly #hash = #Hash;';
EXEC #master_sys_sp_executesql #cmd, N'#Hash VARBINARY(64)',#Hash;
END;
IF(#ProductMajorVersion>=14)
BEGIN
SET #cmd = 'GRANT UNSAFE ASSEMBLY TO tSQLtAssemblyKey;';
END
ELSE
BEGIN
SET #cmd = 'GRANT EXTERNAL ACCESS ASSEMBLY TO tSQLtAssemblyKey;';
END;
EXEC #master_sys_sp_executesql #cmd;
END;
GO
IF OBJECT_ID('tempdb..#PrepareServer') IS NOT NULL DROP PROCEDURE #PrepareServer;
GO
CREATE PROCEDURE #PrepareServer
AS
BEGIN
EXEC #Private_EnableCLR;
EXEC #InstallAssemblyKey;
END;
GO
EXEC #PrepareServer;
GO
I was tested this code, on SQL-Server 2016-2017-2019, worked well.
I am getting below error message when I am trying to run stored procedure.
Msg 7399, Level 16, State 1, Procedure accountupdater, Line 10 The OLE
DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "(null)"
reported an error. Access denied. Msg 7350, Level 16, State 2,
Procedure accountupdater, Line 10 Cannot get the column information
from OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server
"(null)".
Additional information: previously it was working, but after installing MS Office it start to give an error message. We uninstalled MS Office and reinstalled “Microsoft Access Database Engine 2010”. Still getting error message.
Did some research and found that I need to install “Microsoft Access Database Engine 2010”. I did, but still getting the same error message.
ALTER PROCEDURE [dbo].[accountupdater]
AS
DECLARE #accountNum numeric, #businessFEIN varchar(100), #stateID varchar(100), #dbaName varchar(100), #addressLine1 varchar(100), #addressLine2 varchar(100), #city varchar(100), #state varchar(100), #zip varchar(100), #businessName varchar(100)
DECLARE accountCursor CURSOR FAST_FORWARD FOR
SELECT * FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Text; HDR=YES; Database=D:\Innoprise\',
'SELECT * FROM flagstaffAccountUpdate.csv') ors
OPEN accountCursor
--perform first fetch
FETCH NEXT FROM accountCursor INTO #accountNum, #businessFEIN, #stateID, #dbaName, #addressLine1, #addressLine2, #city, #state, #zip, #businessName
--check if there are more rows to fetch
WHILE ##FETCH_STATUS = 0
BEGIN
update BUSINESS SET FEIN=coalesce(#businessFEIN, FEIN), name=coalesce(#businessName, name) WHERE ID = (select business_id from VENDOR v where v.vendornumber=#accountNum);
update DBA set name=coalesce(#dbaName, name) where id = (select primarydba_id from vendor v where v.vendorNumber=#accountNum);
update VENDOR set stateId=coalesce(#stateID, stateID) where vendorNumber=#accountNum;
update ADDRESS set addressLine1=coalesce(#addressLine1,addressLine1), ADDressline2=coalesce(#addressLine2,addressline2),
city=coalesce(#city,city), state=coalesce(#state,state), zipCode=coalesce(#zip,zipCode)
where ID = (select v.address_ID from VENDOR v where v.vendorNumber = #accountNum);
FETCH NEXT FROM accountCursor INTO #accountNum, #businessFEIN, #stateID, #dbaName, #addressLine1, #addressLine2, #city, #state, #zip, #businessName
END
CLOSE accountCursor
DEALLOCATE accountCursor
If you have installed Microsoft Access Database Engine 2010 already,then please execute following queries and restart SQL Server Management Studio or SQL Services.
Refer here
USE [master]
GO
EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', N'AllowInProcess', 1
GO
EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', N'DynamicParameters', 1
GO
I need to create an on-demand export of user data on our website. The user clicks an export button, classic ASP code executes a stored procedure that generates a file via BCP, and the user is prompted to download it.
I've created the sproc, and its working flawlessly when executed from SSMS. The catch is getting it to work from the site with the limited privileges granted to the account connecting to SQL from the website. Here is a snippet:
-- INSERT TEMP DATA
INSERT INTO t_users_tempExport
SELECT * FROM #tempExport
-- show advanced options
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
-- enable xp_cmdshell
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
-- hide advanced options
EXEC sp_configure 'show advanced options', 0
RECONFIGURE
-- EXPORT TO CSV
DECLARE #sql varchar(8000)
SELECT #sql = 'bcp "select * FROM DBNAME.dbo.tempExport WHERE scopeID='''+#randomString+'''" '
+ 'queryout C:\temp\exportResidents_'+CONVERT(varchar(max),#userID)+'.csv -c -t, -T -S'
+ ##servername
EXEC master..xp_cmdshell #sql
-- RETURN FILE NAME
SELECT 'C:\temp\export_'+CONVERT(varchar(max),#userID)+'.csv' AS fileName
The issue is that I cannot enable xp_cmdshell with the privledges granted to the account that is connecting to SQL from the website. Im kind of at a loss as to how to proceed.
Is it possible to include the sysadmin credentials in the call to BCP? Is there some easier option or work around?
I ended up going a completely different route. I created the CSV file from pure ASP code, only using the sproc to return the data.
My SQL scripts are generated from templates. They contain the IP address. There can be a lot of them and the operator can by mistake execute the incorrect script. How the script can check if it was launched on the correct machine? (Otherwise, I would like to print the message and exit.)
Is it possible at all?
Thanks,
Petr
Updated Answer
Here's a script that I found from http://weblogs.sqlteam.com/peterl/archive/2008/07/16/How-to-get-IP-address.aspx, with some modifications to better suit your needs:
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...
Original Answer
It seems like using the Server\Instance name instead of the IP address would be easier to work with, and less likely to break if the server(s) were assigned different IP addresses at some later date.
-- 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');
You can find detailed information about the SERVERPROPERTY function at MSDN: SERVERPROPERTY (Transact-SQL). Although, this function doesn't provide any way to obtain the IP address of the server/instance - there is no built-in function that provides this information.
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
Usage if xp_cmdshell is disabled, parsing Adresses is up to you ...
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
I could provide a xp_GetIP.dll, yet only tested with SQL-Server 2005 32-bit
which you could register via
EXEC sp_addextendedproc xp_GetIP, 'C:\temp\xpGetIP.dll'
Call would be
Declare #IP varchar(100)
exec xp_GetIP #IP output
print #IP
output only : 192.168.69.69
EDIT:
Working to on SQL-Server 2008 R2 64-bit als 64bit DLL
Sorry for reposting, but annoyed of allways missing oportunities of accessing systemadata inside SQL-Server I decided to write a Extended Stored Procedure as Bridge to WMI.
Download http://bummisoft.de/download/XP_WMI.zip
the call would be:
exec xp_wmiv3 'Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE'
the DLL is available for 32bit and 64bit SQLServers and free for non comercial use.
Installation:
EXEC sp_addextendedproc xp_wmiv3, '<Your Path>\XP_WMIV3_DLL.dll'
eg: EXEC sp_addextendedproc xp_wmiv3, 'C:\DLLs\XP_WMIV3_DLL.dll'
Uninstallation
EXEC sp_dropextendedproc xp_wmiv3
Usage
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
Currently tested under SQL-Server 2005 and SQL-Server 2008.