I am trying to generated the script of a database on SQL Server 2008 R2
I got this error
Microsoft.SqlServer.Management.Smo.PropertyCannotBeRetrievedException: Property TextHeader is not available for StoredProcedure '[dbo].[p_SYS_GetQDNPassword]'. This property may not exist for this object, or may not be retrievable due to insufficient access rights. The text is encrypted. at Microsoft.SqlServer.Management.SqlScriptPublish.GeneratePublishPage.worker_DoWork(Object sender, DoWorkEventArgs e) at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e) at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
Could you help please?
I don't know what other information you need, but whatever you need, tell me please to give you.
Using the sp_helptext dbo.p_SYS_GetQDNPassword should give you the result:
"The text for object 'YourProcedureName' is encrypted."
This means that stored procedure is created using WITH ENCRYPTION, and SQL Server internally stores the text with the definition of the object in an obfuscated format
The actual definition of an object is stored in system table sys.sysobjvalues which is not directly accessible. By connecting to SQL Server using the Dedicated Administrator Connection (DAC) you can select the imageval column in which the information is stored
Click on Database Engine Query button:
The Connect To Database Engine dialog will pop out. Type the "admin:" prefix before the server name and you'll be connected to DAC
You can find useful info here in this article
http://www.mssqltips.com/sqlservertip/2964/encrypting-and-decrypting-sql-server-stored-procedures-views-and-userdefined-functions/
When you're connected to DAC run the following script from the article:
SET NOCOUNT ON
GO
ALTER PROCEDURE dbo.TestDecryption WITH ENCRYPTION AS
BEGIN
PRINT 'This text is going to be decrypted'
END
GO
DECLARE #encrypted NVARCHAR(MAX)
SET #encrypted = (
SELECT imageval
FROM sys.sysobjvalues
WHERE OBJECT_NAME(objid) = 'TestDecryption' )
DECLARE #encryptedLength INT
SET #encryptedLength = DATALENGTH(#encrypted) / 2
DECLARE #procedureHeader NVARCHAR(MAX)
SET #procedureHeader = N'ALTER PROCEDURE dbo.TestDecryption WITH ENCRYPTION AS '
SET #procedureHeader = #procedureHeader + REPLICATE(N'-',(#encryptedLength
- LEN(#procedureHeader)))
EXEC sp_executesql #procedureHeader
DECLARE #blankEncrypted NVARCHAR(MAX)
SET #blankEncrypted = (
SELECT imageval
FROM sys.sysobjvalues
WHERE OBJECT_NAME(objid) = 'TestDecryption' )
SET #procedureHeader = N'CREATE PROCEDURE dbo.TestDecryption WITH ENCRYPTION AS '
SET #procedureHeader = #procedureHeader + REPLICATE(N'-',(#encryptedLength
- LEN(#procedureHeader)))
DECLARE #cnt SMALLINT
DECLARE #decryptedChar NCHAR(1)
DECLARE #decryptedMessage NVARCHAR(MAX)
SET #decryptedMessage = ''
SET #cnt = 1
WHILE #cnt <> #encryptedLength
BEGIN
SET #decryptedChar =
NCHAR(
UNICODE(SUBSTRING(
#encrypted, #cnt, 1)) ^
UNICODE(SUBSTRING(
#procedureHeader, #cnt, 1)) ^
UNICODE(SUBSTRING(
#blankEncrypted, #cnt, 1))
)
SET #decryptedMessage = #decryptedMessage + #decryptedChar
SET #cnt = #cnt + 1
END
SELECT #decryptedMessage
Of course change the dbo.TestDecryption with your procedure name in the script :)
This script works for me, hope it helps
Use
sp_helptext dbo.p_SYS_GetQDNPassword
and
Try to alter the stored procedure and try to get script
Related
Like the title says, is there a way to do that?
I've tried dbForge SQL Decryptor but I run into an error
DBCC command 'DBInfo' not supported in this version of SQL Server
Maybe you can reference these tutorials:
Simple Way to Decrypt SQL Server Stored Procedure.
How to decrypt encrypted stored procedures
They all give us a way that using a procedure to decrypt the encrypted stroed procedures.
Example:
create PROCEDURE sp_decrypt_sp (#objectName varchar(50))
AS
DECLARE #OrigSpText1 nvarchar(4000), #OrigSpText2 nvarchar(4000) , #OrigSpText3 nvarchar(4000), #resultsp nvarchar(4000)
declare #i int , #t bigint
--get encrypted data
SET #OrigSpText1=(SELECT ctext FROM syscomments WHERE id = object_id(#objectName))
SET #OrigSpText2='ALTER PROCEDURE '+ #objectName +' WITH ENCRYPTION AS '+REPLICATE('-', 3938)
EXECUTE (#OrigSpText2)
SET #OrigSpText3=(SELECT ctext FROM syscomments WHERE id = object_id(#objectName))
SET #OrigSpText2='CREATE PROCEDURE '+ #objectName +' WITH ENCRYPTION AS '+REPLICATE('-', 4000-62)
--start counter
SET #i=1
--fill temporary variable
SET #resultsp = replicate(N'A', (datalength(#OrigSpText1) / 2))
--loop
WHILE #i<=datalength(#OrigSpText1)/2
BEGIN
--reverse encryption (XOR original+bogus+bogus encrypted)
SET #resultsp = stuff(#resultsp, #i, 1, NCHAR(UNICODE(substring(#OrigSpText1, #i, 1)) ^
(UNICODE(substring(#OrigSpText2, #i, 1)) ^
UNICODE(substring(#OrigSpText3, #i, 1)))))
SET #i=#i+1
END
--drop original SP
EXECUTE ('drop PROCEDURE '+ #objectName)
--remove encryption
--preserve case
SET #resultsp=REPLACE((#resultsp),'WITH ENCRYPTION', '')
SET #resultsp=REPLACE((#resultsp),'With Encryption', '')
SET #resultsp=REPLACE((#resultsp),'with encryption', '')
IF CHARINDEX('WITH ENCRYPTION',UPPER(#resultsp) )>0
SET #resultsp=REPLACE(UPPER(#resultsp),'WITH ENCRYPTION', '')
--replace Stored procedure without enryption
execute( #resultsp)
GO
But for Azure:
Azure SQL Database does not support the WITH ENCRYPTION option object such as stored procedure.
Actually the stored procedure created WITH ENCRYPTION does not encrypt anything in Azure SQL database.
You could reference this link.
Hope this helps.
I need to write a SQL Server 2008R2 compatible script to create a share. The script will be executed from inside VB6 code but I am pretty sure that's a moot point here.
The following is PSEUDOCODE at the end
CREATE PROCEDURE [dbo].[create_Server_share]
#TheShare VARCHAR(50),
#TheDIR VARCHAR(250) = NULL
AS
BEGIN
IF (#TheDIR IS NULL) -- ALLUSERSPROFILE usually C:\Programdata
SET #TheDIR = ENVREFERENCE('%ALLUSERSPROFILE%')+ '\XYZ'
....
I already see that ENVREFERENCE is NOT available in SQL Server 2008 R2 (which is the oldest version I have to accomodate for our clients)
But I am not married to using ENVREFERENCE either - I just want the HOST MACHINE to give me its environment return for ALLUSERSPROFILE (obviously I should not grab this value from the executing code in the application because I will be getting the CLIENT's value instead of the desired HOST server's value; hence my desire to execute it from the T-SQL script)
So do any SQL guru's have some insight into this?
Thanks in advance.
Harry
Can't say this is completely bulletproof, but I past the first few dozen tests.
Thanks to Jeroen Mostert I realized I had my access to %ALLUSERSPROFILES% already on the Host server. the script then became something I could do...
-- create_Server_share.sql written by Harry Abramowski on 6/26/2018
-- we ARE NOT doing these steps in a command line prompt nor in VB6
-- because this share has to be made **ON** THE SERVER!
-- stored procs are a bitch!
go
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF EXISTS(SELECT 1
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = 'create_Server_share'
AND SPECIFIC_SCHEMA = 'dbo')
BEGIN
DROP PROCEDURE create_Server_share
END
go
CREATE PROCEDURE [dbo].[create_Server_share]
#TheShare varchar(50),
#TheDrive char=null,
#TheDIR varchar(250)=null
AS
BEGIN
if (#TheDIR is null)
set #TheDIR = '%ALLUSERSPROFILE%\XYZ'
if (#TheDrive is null)
set #TheDrive = 'X'
DECLARE #answer as varchar(MAX)
declare #myString as varchar(1000)
DECLARE #i INT
-- JUST in case its not already set up, let's enable use of the reconfig in SQL
EXEC sp_configure 'show advanced options', 1; --might not be needed
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1; -- wont hurt to assume it IS needed
RECONFIGURE;
-- net share XYZShare=C:\Programdata\XYZ /grant:everyone,FULL
a_redo:
set #myString = ('net share ' + #TheShare +'=' + #TheDIR + ' /grant:everyone,FULL')
CREATE TABLE #xyzout ([outputtext] varchar(MAX))
Insert into #xyzout (outputtext) EXECUTE xp_cmdshell #myString
-- what about The system cannot find the file specified.???
if exists(select #xyzout.outputtext from #xyzout where #xyzout.outputtext = 'The system cannot find the file specified.')
begin
set #myString = ('mkdir ' + #TheDIR)
EXECUTE xp_cmdshell #mystring
print ('The directory ' + #TheDIR + ' was created')
drop table #xyzout
goto a_redo -- yeah I know!
end
-- was there an error - was it just an "already exists" message? let's see
set #answer = (select top 1 outputtext from #xyzout)
print #answer
-- now update systemProps table so the client machines know there's a share and what drive they should map it to
if charindex('system error',lower(#answer))= 0
IF NOT EXISTS (SELECT a.* FROM syscolumns a, sysobjects b
WHERE a.name = 'XYZShare' AND
a.id = b.id AND
b.name = 'systemProps')
ALTER TABLE system ADD XYZShare NVARCHAR(1000) NULL ;
if charindex('system error',lower(#answer))= 0
begin
update systemProps set XYZShare = (#TheDrive + '=\\' +
CAST(serverproperty('MachineName') as varchar) + '\' + #TheShare );
select systemProps.XYZShare from systemProps;
return 0;
end
else
begin
select * from #xyzout where not(outputtext is null)
return 1;
end
EXEC sp_configure 'xp_cmdshell',0; --let's leave that off?
RECONFIGURE;
DROP TABLE #xyzout
---- if you need to delete the SHARE ITSELF you COULD use this: EXEC XP_CMDSHELL 'net share Xshared /delete'
--HOWEVER you can easily do either from the windows explorer in NETWORK view or My Computer view
END
GRANT EXECUTE ON dbo.create_Server_share TO PUBLIC
GO
Hope this is useful to someone. You guys always come through for me!
Currently working on a script which can update a number of different tables across linked servers. I use 08/12 SQL server management studio.
I am having an issue where I have tried to set up the linked server string as a variable, so I can set this at the beginning and reference when needed through the script. I have been working on the assumption I can declare this as a local variable, as I have for other parts of my script that are updating the local table/server, but when running the script, I receive an incorrect syntax error for the section of code my linked server string variable is located.
My code is structured as:
declare #string varchar(max)
set #string = '[server,instance].[database].dbo.table1'
update #string
set field = updatevariable
where record = identifier
Is it possible to use a linked server as a variable?
You can dynamically construct SQL Update string, and then pass it to exec. Example:
declare
#srv nvarchar(max) = N'[server].[db].[dbo].[table]',
#id int = 100,
#value nvarchar(max) = N'some value',
#sql nvarchar(max)
set #sql = N'update ' + #srv
+ ' set field = ''' + #value + ''' '
+ ' where record = ' + cast(#id as nvarchar)
exec(#sql)
I am using SQL Server 2008 R2 with Classic ASP on Windows Server 2008 R2/IIS. I know classic ASP is pretty long in the tooth but it works fine with the stored procedures I am using. I have a stored procedure that does a simple update on a smalldatetime column, but I am now trying to make this procedure a dynamic one using a variable table name.
The standard procedure that works fine is:
CREATE PROCEDURE [dbo].[spendemerg]
(
#rfid int
)
AS
BEGIN
SET NOCOUNT ON;
Update EmergencyContent
Set content_expiry = DATEADD(minute, -10, GETDATE())
Where content_id = #rfid
END
I am passing the variable parameter #rfid using ADO and it works fine. When I tried to change the procedure to use dynamic SQL to pass the table name as a variable, that's when I got into trouble.
This is the dynamic procedure:
ALTER PROCEDURE [dbo].[spendBroadcast]
#rfid int,
#strTable varchar(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL nvarchar(MAX);
SET #SQL = 'UPDATE ' + #strTable +
' SET content_expiry = '''+ CONVERT(datetime,(DATEADD(minute, -10, GETDATE())), 121) +
''' WHERE content_id = '+ #rfid
EXEC(#SQL)
END
The code runs ok in a query editor using the SQL management studio, but when executed via IIS/CLassic ASP, it fails with the error:
Conversion failed when converting date and/or time from character string
when executing the stored procedure.
This is the ASP code:
Set objCm = Server.CreateObject("ADODB.Command")
Set objRe = Server.CreateObject("ADODB.Recordset")
objCm.ActiveConnection = objConn
objCm.CommandText = "spendBroadcast"
objCm.CommandType = adCmdStoredProc
Set objParam = objCm.CreateParameter("rfid",adInteger,adParamInput,4, strID)
objCm.Parameters.Append objParam
Set objParam = objCm.CreateParameter("strTable",adVarChar,adParamInput,100, strTableName)
objCm.Parameters.Append objParam
Set objRe = objCm.Execute
Any thoughts and help would be greatly appreciated... thanks!
Since you are building a dynamic SQL string then everything should be the same datatype (notice the 2 added conversions below):
SET #SQL = 'UPDATE ' + #strTable + ' SET content_expiry = '''
+ cast(CONVERT(datetime,(DATEADD(minute,-10,GETDATE())),121) as nvarchar(100))
+''' WHERE content_id = ' + cast(#rfid as nvarchar(100))
This is my code I am attempting to run inside a trigger. In a trigger it fails because of the EXEC line. I know this because when I take it out, the code at least finishes execution. If I leave it in it, it doesn't even bother finishing. I know this because if I take out the exec line, it will write the sql line to the error table.
I have to use an EXEC command here to write to the remote server. I can't use a nvarchar variable to define the server. Insert expects an explicit table or a table variable. I need to be able to write to this remote server AND I don't know the name of it until runtime, so I can't be explicit. How do I use an EXEC inside a trigger or is there another way to skin this cat?
DECLARE #acctNum int
DECLARE #tickets nvarchar(MAX)
DECLARE #server nvarchar(64)
DECLARE #sql nvarchar(MAX)
if EXISTS (SELECT * FROM dbo.queueNames WHERE queueName = 'queue1')
BEGIN
SELECT #server = queueServer FROM dbo.queueNames WHERE queueName = 'queue1'
SET #server = #server + '.[AMEETING].dbo.tblMembers'
SELECT TOP 1 #acctNum = AccountNum, #tickets = Tickets FROM dbo.queue1 ORDER BY AccountNum
SET #sql = 'UPDATE ' + #server + ' SET Present = ''1'', Tickets = ''' + #tickets + ''' WHERE AccountNum = ' + convert(nvarchar(64),#acctNum)
INSERT INTO dbo.errors values (#sql)
EXEC (#sql)
DELETE FROM dbo.queue1 WHERE AccountNum = #acctNum
END
I am giving up on this and have gone with using text files on the local server and running processes in the background there to queue the sql statements.