Following my previous question, Previous Question, I have reached till this point using sql-server, but I cannot create the excel files in my directory. Can anyone help me to create excel files? ( I need to create dynamic excel files for example: First 500k --> 1.xlsx; Second 500k --> 2.xlsx and so on.) Attached you will find my T-SQL code.
Use Master
GO
EXEC master.dbo.sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC master.dbo.sp_configure 'xp_cmdshell', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'ad hoc distributed queries', 1
RECONFIGURE
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
USE [AdventureWorksDW2019]
GO
DECLARE #PageNumber AS INT
DECLARE #ExcelFileName as nVarchar(60)
SET #ExcelFileName = cast(#PageNumber as nvarchar)
DECLARE #RowsOfPage AS INT
DECLARE #MaxTablePage AS FLOAT
SET #PageNumber=1
SET #RowsOfPage=500000
SELECT #MaxTablePage = COUNT(CustomerKey)
FROM [dbo].[DimCustomer]
SET #MaxTablePage = CEILING(#MaxTablePage/#RowsOfPage)
WHILE #MaxTablePage >= #PageNumber
BEGIN
SELECT *
FROM [dbo].[DimCustomer]
ORDER BY CustomerKey
OFFSET (#PageNumber-1)*#RowsOfPage ROWS
FETCH NEXT #RowsOfPage ROWS ONLY
DECLARE #FileName nvarchar(400) = #ExcelFileName+ '.xlsx'
DECLARE #FullFileName nvarchar(400) = 'C:\Users\Desktop\CHANGE_LOGS_FOLDER\'+#FileName
DECLARE #sql nvarchar(max)
SET #sql = 'INSERT INTO OPENROWSET(''Microsoft.ACE.OLEDB.12.0'',''Excel 12.0;Database=' +#FullFileName+''', ''SELECT * FROM [Sheet1$]'')
SELECT *
FROM [dbo].[DimCustomer] '''+#ExcelFileName+''''
EXEC (#sql)
SET #PageNumber = #PageNumber + 1
END
Use Master
GO
EXEC master.dbo.sp_configure 'xp_cmdshell', 0
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'ad hoc distributed queries', 0
RECONFIGURE
GO
EXEC master.dbo.sp_configure 'show advanced options', 0
RECONFIGURE WITH OVERRIDE
GO
EXEC master . dbo. sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0' , N'AllowInProcess' , 0
GO
EXEC master . dbo. sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0' , N'DynamicParameters' , 0
GO
Related
We are moving to RDS and one of our apps needs access to tempdb and I am trying to figure out the best way to create a startup job that works with RDS. Currently we are able to create a stored proc that sets up the necessary permissions in the master database and use the EXEC sp_procoption 'AddPermissionsToTempDb', 'startup', 'true' command to set it to start at boot.
In RDS however we are not able to create stored procs in the master database. I tried creating the stored proc in a user-owned db but when I then try to create the startup job with EXEC sp_procoption 'mydb.dbo.AddPermissionsToTempDb', 'startup', 'true' it says it can't find the stored procedure or I do not have permission... Is there another way to accomplish this on RDS?
Was able to find a solution based on Jeroen Mostert's comment so credit goes to them. Here is the full query I used to create the startup job to grant permissions to a list of users to create, control and execute stored procedures on tempdb on an AWS RDS SQL Server instance:
USE msdb
go
declare #job_name varchar(50)
set #job_name = 'AddTempDBPermissionsOnStartup'
exec dbo.sp_delete_job #job_name = #job_name
declare #sql varchar(max)
select #sql = '
Declare #Users Table (username varchar(100) )
insert #Users(username) values (''[user1]''),
(''[user2]''),
(''[user3]'')
use tempdb
CREATE ROLE sp_executor GRANT EXECUTE TO sp_executor
CREATE ROLE sp_manipulator
GRANT CREATE PROCEDURE TO sp_manipulator
GRANT CONTROL TO sp_manipulator
DECLARE #username as NVARCHAR(100);
DECLARE User_Cursor CURSOR FOR
SELECT * from #Users
OPEN User_Cursor;
FETCH NEXT FROM User_Cursor INTO #username;
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #username
IF EXISTS(SELECT * FROM [tempdb].sys.database_principals WHERE type_desc = ''SQL_USER'' AND name = #username)
PRINT '' - user already exists''
ELSE
BEGIN
PRINT '' - creating user''
DECLARE #Sql VARCHAR(MAX)
SET #Sql =
''USE Tempdb'' + char(13) +
''CREATE USER '' + #username + '' FOR LOGIN '' + #username + char(13) +
''EXEC sp_addrolemember sp_executor, '' + #username + char(13) +
''EXEC sp_addrolemember sp_manipulator, '' + #username
EXEC (#Sql)
END
FETCH NEXT FROM User_Cursor INTO #username;
END;
CLOSE User_Cursor;
DEALLOCATE User_Cursor;
GO
'
--Add a job
EXEC dbo.sp_add_job
#job_name = #job_name ;
--Add a job step to run the command
EXEC sp_add_jobstep
#job_name = #job_name,
#step_name = N'job step',
#subsystem = N'TSQL',
#command = #sql
--Schedule the job to run at startup
exec sp_add_jobschedule #job_name = #job_name,
#name = 'RunAtStartSchedule',
#freq_type=64
--Add the job to the SQL Server Server
EXEC dbo.sp_add_jobserver
#job_name = #job_name
I have installed SQL Server Express on my machine and enabled and configured FILESTREAM to store and retrieve pdf's from SQL Server. I have successfully uploaded files to my table as BLOB's, but I am having difficulty retrieving them. My approach is to use a temporary directory to create the files in so I can open them. I have the following code:
I have configured ole automation
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
I have the following record in my table BusinessFiles:
FileID 415578C7-B058-49A5-A1E4-5A4E7218EA19
InvoiceID 99999
FileName file1
FileType pdf
ImageFile 0x255044462D312…
This next piece of code apparently will create the file from the filestream.
DECLARE
#FILE VARBINARY(MAX)
,#FILEPATH VARCHAR(MAX)
,#ObjectToken INT
,#FileType VARCHAR(MAX)
,#FILENAME VARCHAR(MAX)
Set #FILENAME = (SELECT [FileName] FROM BusinessFiles where FileID = '415578C7-B058-49A5-A1E4-5A4E7218EA19')
Set #FileType = (SELECT FileType FROM BusinessFiles where FileID = '415578C7-B058-49A5-A1E4-5A4E7218EA19')
SELECT #FILE = ImageFile FROM BusinessFiles where FileID = '415578C7-B058-49A5-A1E4-5A4E7218EA19'
Set #FILEPATH = CONCAT('C:\Users\user\Desktop\', #FILENAME,'.',#FileType)
EXEC sp_OACREATE 'ADODB.Stream', #ObjectToken OUTPUT
EXEC sp_OASetProperty #ObjectToken, 'Type', 1
EXEC sp_OAMethod #ObjectToken, 'Open'
EXEC sp_OAMethod #ObjectToken, 'Write', NULL, #FILE
EXEC sp_OAMethod #ObjectToken, 'SaveToFile', NULL, #FILEPATH, 2
EXEC sp_OAMethod #ObjectToken, 'Close'
EXEC sp_OADestroy #ObjectToken
Go
This code runs and I get the Commands Completed successfully message. However there is nothing in my folder C:\Users\user\Desktop. Is there something I'm missing? Thanks;
I've verified the file path is correct and all the set's are good.
Knowing the permissions of SQL Server will fix the SaveToFile Issue. In my case, I changed the SavetoFile Directory to C:\temp.
I want to create an assembly in SQL Server 2008 R2 if it does not exist in the specific database by using a stored procedure, giving the path of the file as a parameter.
USE DBName
GO
CREATE PROCEDURE spCreateAssembly
#FilePath varchar(max)
AS
BEGIN
IF NOT EXISTS (select 1 from sys.assembly_files f
full outer join sys.assemblies a on f.assembly_id=a.assembly_id
full outer join sys.assembly_modules m on a.assembly_id=m.assembly_id
WHERE a.name = 'Lib1')
BEGIN
sp_configure 'show advanced options', 1
RECONFIGURE
GO
sp_configure 'clr enabled', 1
RECONFIGURE
GO
sp_configure 'show advanced options', 0
RECONFIGURE
GO
Create Assembly Lib1 from #FilePath with Permission_set = SAFE
END
END
But getting an error:
Msg 102, Level 15, State 1, Procedure spCreateAssembly, Line 14
Incorrect syntax near 'sp_configure'.
Try this:
CREATE PROCEDURE spCreateAssembly
#FilePath varchar(max)
AS
BEGIN
IF NOT EXISTS (select 1 from sys.assembly_files f
full outer join sys.assemblies a on f.assembly_id=a.assembly_id
full outer join sys.assembly_modules m on a.assembly_id=m.assembly_id
WHERE a.name = 'Lib1')
BEGIN
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'clr enabled', 1
RECONFIGURE
EXEC sp_configure 'show advanced options', 0
RECONFIGURE
Create Assembly Lib1 from #FilePath with Permission_set = SAFE
END
END
You cannot use GO in stored procedure.
I'm using an EXEC statement to execute a stored procedure that returns a table-value. I'd like to insert the results of this statement into a temporary table, but I do not want to define this temp table first. Is this possible?
I'm thinking along the lines of how an SELECT * INTO #temp FROM ... does not require #temp to be defined first. Is is possible to do the same thing with the results of an EXEC statement?
Here is the solution you are looking for -
exec sp_configure 'show advanced option',1
reconfigure
go
exec sp_configure 'ad hoc distributed queries',1
reconfigure
go
--In case there are no parameters, use this--
select * into #a
from openrowset('sqlncli','server=localhost;trusted_connection=yes','exec dbo.yourprocedure')
--In case there are parameters in stored procedure, use this---
declare #sql nvarchar(max)
declare #param1 varchar(100)
set #sql = 'select * into #a
from openrowset(''sqlncli'',''server=localhost;trusted_connection=yes'',''exec dbo.yourprocedure ''' + #param1 + ')'
exec sp_executesql #sql
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.