Encrypted query in sql server - sql

I want to execute a query in our client's server using remove access. If I execute a query something like this Update abc set col1=12 where id = 2 they will understand what we are doing. So I want some method for encryption and decryption like this:
In our server I encrypt a query like this:
encrypt(Update abc set col1=12 where id = 2)
So I get output like:
0x0100CF465B7B12625EF019E157120D58DD46569AC7BF4118455D12625EF019E157120D58DD46569AC7BF4118455D
And I execute a this encrypted query on client's machine like this:
decrypt(0x0100CF465B7B12625EF019E157120D58DD46569AC7BF4118455D12625EF019E157120D58DD46569AC7BF4118455D)
So our client can't understand what we have executed.

you can create a simple decrypt function like this..
create proc exec_decrypt(#sql_str varbinary(8000))
as
begin
declare #qry varchar(8000);
select #qry=cast(#sql_str as varchar(8000));
exec(#qry);
end
which accepts a varbinary string and converts to varchar and then execute it..
You can generate the encrypted query by using the satament below
select CAST('UPDATE users set name =''alex''' as varbinary(8000))
then execute the proc exec_decrypt in client place by passing the output of the above query as the parameter for the procedure..
Ex: exec_decrypt 0x55504441544520757365727320736574206E616D65203D27616C657827
Hope this will work for you.. Please note that client should not have any permission on the
proc exec_decrypt

The only way I have found to ensure that no one can view your queries is to put them in a function or procedure using 'with encryption'. Run the below code to see for yourself. Dynamic SQL suggested in the earlier answer doesn't fully solve your problem.
create procedure dbo.dummy_drop_me with encryption as select t.* from sys.dm_exec_requests r cross apply sys.dm_exec_sql_text (r.sql_handle) t where r.session_id = ##spid
go
exec dbo.dummy_drop_me
go
select t.* from sys.dm_exec_requests r cross apply sys.dm_exec_sql_text (r.sql_handle) t where r.session_id = ##spid
go
exec ('select t.* from sys.dm_exec_requests r cross apply sys.dm_exec_sql_text (r.sql_handle) t where r.session_id = ##spid')
The only way I have found to keep someone from capturing your functions and procedures is to create them in their own database on a server where no one has access. Then, attach a copy of the database to the servers where you need them.

In my opinion, With Encryption is generally counter-productive as there are a number of Sql Server decryption tools. ie dbForge's DB Decryptor. I just used this to decrypt a database's T-SQL, so I could export DACPAC's and BACPAC's for use in Azure DevOps automated deployments. With Encryption causes DACPAC and BACPAC exports to fail. This means, if you implement With Encryption you cannot use DACPAC to create update scripts for DB Patches or direct updates, you cannot use Visual Studio Sql Server Tools projects, which makes DB development harder. You have not secured anything, just made it harder for Dev's and Op's to do their jobs.

Related

SQL simple query on multiple linked servers & databases

I have this simple SQL query in SSMS select * from dbo.table1 where sucode = 'a002'
I am trying to learn how to run this on all linked servers on databases ending in %live
I've never done this before and what I have seen online hasn't really helped.
I know I need to have QUOTENAME(d.name, '''') ....WHERE NAME like '%live' for the database name and possibly the same for the server? Or maybe an OPENQUERY for the server? Or a link?
If anyone has a template they use or any advise that would be hugely appreciated.
You can use undocumented stored procedure MS_ForeachDb to execute the query against each database. You can use sys.servers to get the list of linked servers and run them against each linked server.
Read MS_ForeachDB
Read about sys.servers
SELECT 'SELECT * FROM OPENQUERY(' + name + ',''EXECUTE master.sys.sp_MSforeachdb ''USE [?];select * from dbo.table1 where sucode = ''a002'''')'
FROM sys.servers WHERE is_linked = 1; -- avoid pulling from local server
Note: Using undocumented procedures is not recommended. Read more on this using undocumented procedures bad practice

Validating a Dynamic SQL DELETE statement without executing the statement [duplicate]

I have access to an Access database and within that database are fields filled with TSQL queries. These queries are processed by T-SQL on a server. So when I write these SQL queries and put them into a field for use by the end server, I'm unable to validate the syntax/etc. I could create a temporary query in that Access database, but it's not the same query language. For example, Access would correctly use IIF but TSQL would not (it would instead be CASE).
I don't have direct access to this server with TSQL, is there a way I can validate my T-SQL queries (for syntax and the like)? Perhaps a web tool online?
I should note I do not have access to the SQL server. Only the Access db and that alone. I understand it will not validate table names and the like, I wouldn't expect it to.
Actually, a combination of MattMc3's answer and FremenFreedom's answer should work.
Download SQL Express.
Then, declare the following stored procedure:
create procedure IsValidSQL (#sql varchar(max)) as
begin
begin try
set #sql = 'set parseonly on;'+#sql;
exec(#sql);
end try
begin catch
return(1);
end catch;
return(0);
end; -- IsValidSQL
You can test it with:
declare #retval int;
exec #retval = IsValidSQL 'select iif(val, 0, 1) from t';
select #retval
or with:
declare #retval int;
exec #retval = IsValidSQL 'select val from t';
select #retval
Note: this will catch the IIF() issue. It will not catch anything related to the table structures or column structures. You would need the schema for that and a slightly different approach ("select top 0 * from () t") woudl do it.
You might be able to do something with SQL Fiddle online. However, I would suggest having a local copy of the database.
You can parse your T-SQL to check for valid syntax by executing it on the SQL Server machine with a SET PARSEONLY ON as the first line of your script. It will not validate table or field names, but will provide you with any syntax errors.
The Data Dude (Gert Drapers) describes how to use the built-in SQL Server T-SQL parser in your application here:
Getting to the Crown Jewels
If you want to only check the validity of the SQL statements that you have - this might be a nice way to go, and it doesn't require SQL Server per se to be installed where you run your unit tests.
It's a .NET based approach, and it cannot - of course - validate object names in your database if you're not using a live database - but it can catch syntactical errors in your T-SQL statements.
You can use the NOEXEC option:
SET NOEXEC ON
SELECT 1 AS Test
SET NOEXEC OFF
Is SQL Server Management Studio Express (free download) able to connect to regular SQL Server instances? If so, perhaps you could test the queries there. Even if you could not connect to the actual server, you might be able to create a test version of your database in Express that would at least allow you to catch syntax and naming problems.
If they are fairly static, convert them into stored procedures in the Sql Database and then just call them from access.

Run complex update query on remote server using OPENROWSET

Could you please help me with below task. I need to run below query on remote server
UPDATE prod
SET prod.count = ( SELECT SUM(Inv) FROM cost WHERE pID = prod.ID)
WHERE (( SELECT COUNT(id) FROM Cost WHERE pID = prod.ID ) > 0)
I have tried to use OPENROWSET but do not have enough experience working with it and all online examples with OPENROWSET that I saw use only one table. Can you please give me an idea how to modify this query to use OPENROWSET or ideas of any other solutions?
You can use direct linked server or OPENQUERY (linked_server_name ,'your query').
Best way to to this is to create procedure on target instance and use only easy exec on linked server to run procedure.
exec LinkedServer.TargetDB.TargerSc.NewProcedure
Openrowset is used to "open row set" - primary to access remote data, to modify remote data is openquery.

SQL reporting invalid syntax when run in Power BI

I have written an SQL script which runs fine when executed directly in SQL Management Studio. However, when entering it into Power BI as a source, it reports that it has an incorrect syntax.
This is the query:
EXEC "dbo"."p_get_bank_balance" '2'
However, the syntax is apparently incorrect? See Picture:
Any help is much appreciated.
EDIT ***
When the double quotes are removed (as per Tab Alleman's suggestion):
I found time ago the same problem online on power bi site:
http://community.powerbi.com/t5/Desktop/Use-SQL-Store-Procedure-in-Power-BI/td-p/20269
You must be using DirectQuery mode, in which you cannot connect to data with stored procedures. Try again using Import mode or just use a SELECT statement directly.
In DirectQuery mode, PowerBI automatically wraps your query like so: select * from ( [your query] ), and if you attempt this in SSMS with a stored procedure i.e.
select * from (exec dbo.getData)
You get the error you see above.
The solution is you have to place your stored procedure call in an OPENQUERY call to your local server i.e.
select * from OPENQUERY(localServer, 'DatabaseName.dbo.getData')
Prerequisites would be: enabling local server access in OPENQUERY with
exec sp_serveroption #server = 'YourServerName'
,#optname = 'DATA ACCESS'
,#optvalue = 'TRUE'
And then making sure you use three-part notation in the OPENQUERY as all calls there default to the master database
With "Import" data connectivity mode Stored Procedures work
With "Direct Query" data connectivity mode, the query syntax must be like below:
declare #sqlCommand varchar(100) = 'dbo.p_get_bank_balance'
declare #p1 int = 2
exec #sqlCommand #p1 = #p1
Remerber: max one data source connection with Direct Query. If you want to call much SP, only one can be in Direct Query mode, the others in Import mode
Try using Import instead of Direct Query. It may be showing error cause you are using Temp table in it. Create query using sub query and remove Temp table and try it. Or you can use as Import instead of Direct Query it will work.

Ways to validate T-SQL queries?

I have access to an Access database and within that database are fields filled with TSQL queries. These queries are processed by T-SQL on a server. So when I write these SQL queries and put them into a field for use by the end server, I'm unable to validate the syntax/etc. I could create a temporary query in that Access database, but it's not the same query language. For example, Access would correctly use IIF but TSQL would not (it would instead be CASE).
I don't have direct access to this server with TSQL, is there a way I can validate my T-SQL queries (for syntax and the like)? Perhaps a web tool online?
I should note I do not have access to the SQL server. Only the Access db and that alone. I understand it will not validate table names and the like, I wouldn't expect it to.
Actually, a combination of MattMc3's answer and FremenFreedom's answer should work.
Download SQL Express.
Then, declare the following stored procedure:
create procedure IsValidSQL (#sql varchar(max)) as
begin
begin try
set #sql = 'set parseonly on;'+#sql;
exec(#sql);
end try
begin catch
return(1);
end catch;
return(0);
end; -- IsValidSQL
You can test it with:
declare #retval int;
exec #retval = IsValidSQL 'select iif(val, 0, 1) from t';
select #retval
or with:
declare #retval int;
exec #retval = IsValidSQL 'select val from t';
select #retval
Note: this will catch the IIF() issue. It will not catch anything related to the table structures or column structures. You would need the schema for that and a slightly different approach ("select top 0 * from () t") woudl do it.
You might be able to do something with SQL Fiddle online. However, I would suggest having a local copy of the database.
You can parse your T-SQL to check for valid syntax by executing it on the SQL Server machine with a SET PARSEONLY ON as the first line of your script. It will not validate table or field names, but will provide you with any syntax errors.
The Data Dude (Gert Drapers) describes how to use the built-in SQL Server T-SQL parser in your application here:
Getting to the Crown Jewels
If you want to only check the validity of the SQL statements that you have - this might be a nice way to go, and it doesn't require SQL Server per se to be installed where you run your unit tests.
It's a .NET based approach, and it cannot - of course - validate object names in your database if you're not using a live database - but it can catch syntactical errors in your T-SQL statements.
You can use the NOEXEC option:
SET NOEXEC ON
SELECT 1 AS Test
SET NOEXEC OFF
Is SQL Server Management Studio Express (free download) able to connect to regular SQL Server instances? If so, perhaps you could test the queries there. Even if you could not connect to the actual server, you might be able to create a test version of your database in Express that would at least allow you to catch syntax and naming problems.
If they are fairly static, convert them into stored procedures in the Sql Database and then just call them from access.