Showing posts with label t-SQL. Show all posts
Showing posts with label t-SQL. Show all posts

Friday, 13 April 2012

How to pass a DataTable as table parameter to stored procedure



SQL , C# :pass data table as table parameter to stored procedure

here is my references:




--This is the database table
CREATE TABLE dbo.SampleTable
(
Id int NOT NULL IDENTITY (1, 1),
SampleString nvarchar(64) NOT NULL,
SampleInt int NULL
) ON [PRIMARY]


-- Create a table data type
CREATE TYPE [dbo].[SampleDataType] As Table
(
--This type has structure similar to the DB table 
SampleString Nvarchar(64) Not Null -- Having one String
, SampleInt Int -- and one int
)


--This is the Stored Procedure
CREATE PROCEDURE [dbo].[SampleProcedure]
(
-- which accepts one table value parameter. 
-- It should be noted that the parameter is readonly
@Sample As [dbo].[SampleDataType] Readonly
)
AS
 
Begin
-- We simply insert values into the DB table from the parameter
-- The table value parameter can be used like a table with only read rights
Insert Into SampleTable(SampleString,SampleInt)
Select SampleString, SampleInt From @Sample
End


The DB Test Script
-- This is the sample script to test the SP
-- An instance of the Table parameter type is created
Declare @SampelData As [dbo].[SampleDataType]
-- and then filled with the set of values
Insert Into @SampelData(SampleString, SampleInt) Values('1',1);
Insert Into @SampelData(SampleString, SampleInt) Values('2',null);
Insert Into @SampelData(SampleString, SampleInt) Values('3',3);
Select * From @SampelData
-- we then call the SP to store the values
Exec SampleProcedure @SampelData
Select * From SampleTable


The C# Code

Representing the Data

//To represent the table parameter in C#, we need to either 
//have a set of entities which are IEnumreable 
//or a data reader or a Data table.
//In this example we create a data table with same name as the type we have in the DB 
DataTable dataTable = new DataTable("SampleDataType"); 
//we create column names as per the type in DB 
dataTable.Columns.Add("SampleString", typeof(string)); 
dataTable.Columns.Add("SampleInt", typeof(Int32)); 
//and fill in some values 
dataTable.Rows.Add("99", 99); 
dataTable.Rows.Add("98", null); 
dataTable.Rows.Add("97", 99); 

Passing the Data

SqlParameter parameter = new SqlParameter(); 
//The parameter for the SP must be of SqlDbType.Structured 
parameter.ParameterName="@Sample"; 
parameter.SqlDbType = System.Data.SqlDbType.Structured; 
parameter.Value = dataTable; 
 command.Parameters.Add(parameter); 

How to associate all jobs to an operator ( base on their Job ID)

SQL : associate all jobs to an operator ( base on their Job ID)

use msdb
go


SELECT name ,
sql = '
EXEC msdb.dbo.sp_update_job @job_id=N''' +  convert(varchar(200), job_ID ) + ''',
              @notify_level_email=2,
              @notify_level_netsend=2,
              @notify_level_page=2,
              @notify_email_operator_name=N''SQLServerAlertMaint''

              go

              '

FROM dbo.sysjobs
order by  name
--WHERE program_name like 'SQLAgent - TSQL JobStep%'


What's the execute order of the different parts of a SQL select statement?

Monday, 27 September 2010

Search a text in stored procedure source code

use master
go


-- =============================================
-- Description: Search a text in stored procedure source code.
-- @text - any text to find, search is done by like '%text%'
-- @dbname - database where to search,
--         - if omitted, all databases in the SQL server instance
-- =============================================
alter PROCEDURE [dbo].[sp_FindTextInsideProcedure]
  @text varchar(250),
  @dbname varchar(64) = null ,
  @OrderByColumn int = 1 ,
  @Level int = null
AS BEGIN
SET NOCOUNT ON;

if ( @dbname is null or @dbname like '%[_]%' or @dbname like '%[%]%' ) and @Level is null
  begin
  /*
   -- cursor programming
  
    --enumerate all databases.
  DECLARE #db CURSOR FOR Select Name from master..sysdatabases where ( @dbname is null or Name like @dbname   )
  declare @c_dbname varchar(64)

     
  OPEN #db FETCH #db INTO @c_dbname
  while @@FETCH_STATUS <> -1 --and @MyCount < 500
   begin
     execute sp_FindTextInsideProcedure @text=@text, @dbname = @c_dbname
     FETCH #db INTO @c_dbname
   end 
  CLOSE #db DEALLOCATE #db
 
  */
      -- no cursor

      --enumerate all databases.
      Select Name
      into #db
      from master..sysdatabases
      where ( @dbname is null or Name like @dbname   )

      declare @c_dbname varchar(64)
      set @c_dbname = (select top 1 Name from #db)
      declare @result table ( db varchar(64) , name varchar(256) , [definition] nvarchar(max))

      while ( @c_dbname is not null )
      begin
            insert into @result
            execute sp_FindTextInsideProcedure @text=@text, @dbname = @c_dbname , @Level =1

            delete #db
            where name = @c_dbname

            -- get the next database name
            set @c_dbname = (select top 1 Name from #db)
      end 

      drop table #db
      select * from @result r
      order by case @OrderByColumn
                              when 1 then r.db
                              when 2 then r.name 
                              when 3 then r.[definition] 
                              else  r.db
                  end
     
end --if @dbname is null
else
begin --@dbname is not null
  declare @sql varchar(4000)
  --create the find like command
  select @sql = 'select ''' + @dbname + ''' as db, o.name,m.definition '
                        + ' from ['+@dbname+'].sys.sql_modules m '
                        + ' inner join ['+@dbname+']..sysobjects o '
                        + '         on m.object_id=o.id'
                        + ' where [definition] like ''%'+@text+'%'''
  if (@Level is null)
  begin
      select @sql = @sql + 'order by case ' + convert(varchar , @OrderByColumn ) 
                        + '                     when 1 then ''' + @dbname + ''''
                        + '                     when 2 then  o.name  '
                        + '                     when 3 then m.definition  '
                        + '                     else   ''' + @dbname + ''''
                        + '         end'
  end
  execute (@sql)
end --@dbname is not null
END



Xp_cmdshell and permissions: How to use a proxy to run OS Command from SQl server agent (without administrator account)

Xp_cmdshell and permissions
This blog post was inspired from a newsgroup discussion. The question basically is:
What do you need to do in order to use xp_cmdshell?
Note that there are obvious security implications of doing this. (I'm not recommending usage of xp_cmdshell in general, this is atechnical blog post!) We first need to think about what happens here, from an architectural level:
Somebody who has logged in to SQL Server executes xp_cmdshell. For this, SQL Server need to spawn a process in Windows. A process in Windows need to execute in a Windows user account.
So, what Windows account is used? If the SQL Server login who is executing xp_cmdshell is sysadmin, then SQL Server will use the service account (it will not "pretend to be somebody else"). But if the login isn't sysadmin, then we need to configure what Windows account to be used (using sp_xp_cmdshell_proxy_account). Note that this configuration is the same for all non-sysadmins!
But there's a little bit more to it. Below is an outline of what need to be done. Step 2 and 3 are only needed if the one who is to execute xp_cmdshell isn't sysadmin. Note that the steps don't have to be performed in the order listed below.
1.    We need to allow usage of xp_cmdshell in general (on 2005). Use "Surface Area Configuration" or sp_configure for this.
2.    We need to have a user in the master database which has execute permission on xp_cmdshell. If you are uncertain about the difference between logins and users, you should read up about it in BOL.
3.    We need to say what Windows account should be used when a non-sysadmin user is executing xp_cmdshell.
So, here's the TSQL script that does all above:
--1, allow xp_cmdshell
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
GO
--2, grant permission to xp_cmdshell
USE master
CREATE LOGIN JohnDoe WITH PASSWORD = 'jlkw#.6('
--Note, we are in the master database!!!
CREATE USER JohnDoe FROM LOGIN JohnDoe
--Run as login x
EXECUTE AS login = 'JohnDoe'
--Below fails, no execute permission on xp_cmdshell
EXEC xp_cmdshell 'DIR C:\*.*'
REVERT
GO
--Note, we are in the master database!!!
GRANT EXECUTE ON xp_cmdshell TO JohnDoe
--Try again
EXECUTE AS login = 'JohnDoe'
--Execution of xp_cmdshell is allowed.
--But I haven't configured the proxy account...
EXEC xp_cmdshell 'DIR C:\*.*'
REVERT
GO
--3, specify the proxy account for non-syadmins
--Replace obvious parts!
EXEC sp_xp_cmdshell_proxy_account 'Domain\WinAccount','pwd'
EXECUTE AS login = 'JohnDoe'
--Execution of xp_cmdshell is allowed.
--And executes successfully!!!
EXEC xp_cmdshell 'DIR C:\*.*'
REVERT
 --Cleanup
EXEC sp_xp_cmdshell_proxy_account null
DROP USER JohnDoe
DROP LOGIN JohnDoe
EXEC sp_configure 'xp_cmdshell', 0
RECONFIGURE
·          My recommendation is to make a user in Active Directory and then import it into SQL server with user interface to avoid the Create login command which sometimes is a bit  annoying.