SQL Server: Error in Cursorless stored procedure - stored-procedures
I'm having trouble with this stored procedure, could you please help.
This is error I'm getting - running all this via Oracle Sql developer on SQL Server 2000 hosted elsewhere.
Error
Error starting at line 1 in command:
execute dbo.OF_ASEQ_EH_BROWNBIN 'dbo.EH_Brownbin_Josh','Match', 1
Error report:
Incorrect syntax near the keyword 'BEGIN'.
Procedure
ALTER PROCEDURE [dbo].[OF_ASEQ_EH_BROWNBIN]
#JvarTable Varchar(250),
#varColumn Varchar(250),
#optInterval int
AS
declare #Sql_string nvarchar(4000)
declare #myERROR int
declare #myRowCount int
declare #topseed int
declare #stg_topseed varchar(100)
-- Temp table for rows with nulls in specific column
declare #RowCnt int
declare #MaxRows int
declare #col_Name nvarchar(250)
declare #col_UPRN nvarchar(250)
declare #col_JoinedOn smalldatetime
begin
set #Sql_string = 'select top 1 ' + #varColumn + ' from ' + #JvarTable + ' order by convert(int, ' + #varColumn + ') desc'
set #stg_topseed = #Sql_string
set #topseed = convert(int, #stg_topseed)
SELECT #myERROR = ##ERROR, #myRowCOUNT = ##ROWCOUNT
IF #myERROR != 0 GOTO HANDLE_ERROR
select #RowCnt = 1
declare #Import table
(
rownum int IDENTITY (1, 1) Primary key NOT NULL ,
col_Name nvarchar(250),
col_UPRN nvarchar(250),
col_JoinedOn smalldatetime
)
set #sql_string = 'insert into #Import (col_Name, col_UPRN, col_JoinedOn) select Name, UPRN, JoinedOn from ' + #JvarTable + ' where ' + #varColumn +' is null'
exec #Sql_string
SELECT #myERROR = ##ERROR, #myRowCOUNT = ##ROWCOUNT
IF #myERROR != 0 GOTO HANDLE_ERROR
select #MaxRows=count(*) from #Import
SELECT #myERROR = ##ERROR, #myRowCOUNT = ##ROWCOUNT
IF #myERROR != 0 GOTO HANDLE_ERROR
-- Next new seed
select #topseed = #topseed + #optInterval
<br/>
while #RowCnt <= #MaxRows
begin
select #col_Name = col_Name from #Import where rownum = #RowCnt
select #col_UPRN = col_UPRN from #Import where rownum = #RowCnt
select #col_JoinedOn = col_JoinedOn from #Import where rownum = #RowCnt
set #Sql_string = 'update ' + #JvarTable + ' set ' + #varColumn + ' = cast((' + #topseed + ') as char) where Name = ''' + #col_Name + ''' and UPRN = ''' + #col_UPRN + ''' and JoinedOn = ''' + #col_JoinedOn + ''' '
exec (#Sql_string)
select #topseed = #topseed + #optInterval
Select #RowCnt = #RowCnt + 1
end
SELECT #myERROR = ##ERROR, #myRowCOUNT = ##ROWCOUNT
IF #myERROR != 0 GOTO HANDLE_ERROR
HANDLE_ERROR:
RETURN #myERROR
end
Whereas in Oracle, you need to have DECLARE - BEGIN - END, in MSSQL you do not have to use the BEGIN/END keywords on the procedure body.
Note that the label HANDLE_ERROR: is outside the BEGIN/END.
My guess is that removing the BEGIN (after the DECLARE block) and the END (before SELECT #myERROR=...), the error goes away.
Edit:
I guess I don't get the following statement:
set #Sql_string = 'select top 1 ' + #varColumn + ' from ' + #JvarTable + ' order by convert(int, ' + #varColumn + ') desc'
set #stg_topseed = #Sql_string
set #topseed = convert(int, #stg_topseed)
You assign a string var, copy the value to another string var, and, instead of executing the SQL statement, you cast the string var into an int. (?)
There were several errors in that code and there's probably a better, set based, way to solve the problem this stored procedure is for. (But that's another question and requires knowledge of the target tables that was not provided.)
The following code should be a step closer to what you're looking for.
Changes:
Edited suspicious code, cast((' + #topseed + ') as char) is that column really char? or is it varchar(something)?
Corrected logic around #topseed fetch.
Corrected logic around Import table use.
Corrected update SQL generation.
Removed extraneous Begin/ENDs.
Removed extraneous HTML (<br/>).
Wrapped procedure with Begin/END.
Added Go at the end.
Code:
ALTER PROCEDURE [dbo].[OF_ASEQ_EH_BROWNBIN]
#JvarTable Varchar(250),
#varColumn Varchar(250),
#optInterval int
AS
BEGIN
DECLARE #Sql_string nvarchar(4000)
DECLARE #myERROR int
DECLARE #myRowCount int
DECLARE #topseed int
DECLARE #stg_topseed varchar(100)
-- Temp table for rows with nulls in specific column
DECLARE #RowCnt int
DECLARE #MaxRows int
DECLARE #col_Name nvarchar(250)
DECLARE #col_UPRN nvarchar(250)
DECLARE #col_JoinedOn smalldatetime
SET #Sql_string = 'select top 1 #stg_topseed = ' + #varColumn + ' from ' + #JvarTable + ' order by convert(int, ' + #varColumn + ') desc'
EXEC SP_EXECUTESQL #Sql_string, N'#stg_topseed varchar(100) OUTPUT', #stg_topseed OUTPUT
SELECT #myERROR = ##ERROR, #myRowCOUNT = ##ROWCOUNT
IF #myERROR != 0 GOTO HANDLE_ERROR
SET #topseed = CONVERT(int, #stg_topseed)
/* Can't use a table variable with EXEC and/or SP_EXECUTESQL.
Therefore, forced to use a temporary table.
*/
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('#Import') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
DROP TABLE #Import
CREATE table #Import
(
rownum int IDENTITY (1, 1) Primary key NOT NULL,
col_Name nvarchar(250),
col_UPRN nvarchar(250),
col_JoinedOn smalldatetime
)
SET #sql_string = 'insert into #Import (col_Name, col_UPRN, col_JoinedOn) select Name, UPRN, JoinedOn from ' + #JvarTable + ' where ' + #varColumn +' is null'
EXEC (#Sql_string)
SELECT #myERROR = ##ERROR, #myRowCOUNT = ##ROWCOUNT
IF #myERROR != 0 GOTO HANDLE_ERROR
SELECT #MaxRows=count(*) from #Import
SELECT #myERROR = ##ERROR, #myRowCOUNT = ##ROWCOUNT
IF #myERROR != 0 GOTO HANDLE_ERROR
-- Next new seed
SELECT #topseed = #topseed + #optInterval
SELECT #RowCnt = 1
WHILE #RowCnt <= #MaxRows
BEGIN
SELECT #col_Name = col_Name from #Import where rownum = #RowCnt
SELECT #col_UPRN = col_UPRN from #Import where rownum = #RowCnt
SELECT #col_JoinedOn = col_JoinedOn from #Import where rownum = #RowCnt
SET #Sql_string = 'update ' + #JvarTable + ' set ' + #varColumn + ' = ''' + CAST (#topseed AS varchar(250)) + ''' where Name = ''' + #col_Name + ''' and UPRN = ''' + #col_UPRN + ''' and JoinedOn = ''' + CAST(#col_JoinedOn AS varchar(250)) + ''' '
EXEC (#Sql_string)
SELECT #topseed = #topseed + #optInterval
SELECT #RowCnt = #RowCnt + 1
END
SELECT #myERROR = ##ERROR, #myRowCOUNT = ##ROWCOUNT
IF #myERROR != 0 GOTO HANDLE_ERROR
HANDLE_ERROR:
RETURN #myERROR
END
GO
I've been doing housekeeping on StackOverflow, and realised I hadn't (or accepted) answered the question I asked a long time ago. I couldn't remember which method/work-around I decided on, but I felt it's important to upload my accepted and working script, although I no longer need it.
Nevertheless, I sincerely hope this code will help the next person who has similar question to mine.
CREATE PROCEDURE [dbo].[OF_ASEQ_EH_BROWNBIN] #JvarTable nvarchar(250), #varColumn nvarchar(250), #optInterval int AS
/*
Procedure OF_ASEQ_EH_BROWNBIN
Created by Joshua White
When 20100902
Purpose To fill up column with new sequence numbers
Arguments JvarTable - Table name
varColumn - Column name
optInterval - Steps in increment in building new sequence (Should be 1 (one))
Example script to begin procedure
EXECUTE [dbo].[OF_ASEQ_EH_BROWNBIN] 'EH_Brownbin_Josh', 'Match', 1
PLEASE NOTE - Typically Stored Procedures are supposed to be flexible to work on
any tables, but due to complications with SQL Server 2000 and problems with
Cursors, we have to use manual scripts and this Stored Procedure will only work
on EH_BrownBin table ONLY.
Any questions about this, please send email to
<email deleted>
*/
declare #Sql_string nvarchar(4000)
declare #myERROR int
declare #myRowCount int
/* Fetching the last number in rows of table in question */
declare #topseed int
declare #stg_topseed varchar(100)
-- Temp table for rows with nulls in specific column
declare #RowCnt int
declare #MaxRows int
declare #rc int
declare #colu_Name nvarchar(250)
declare #colu_UPRN nvarchar(250)
declare #colu_JoinedOn smalldatetime
Begin
set #stg_topseed = 'select top 1 ' + #varColumn + ' from ' + #JvarTable + ' order by convert(int, ' + #varColumn + ') desc'
exec (#stg_topseed)
/* Begin collecting all rows with nulls in specified column */
select #RowCnt = 1
declare #Import table
(
rownum int IDENTITY (1, 1) Primary key NOT NULL ,
colu_Name nvarchar(250),
colu_UPRN nvarchar(250),
colu_JoinedOn smalldatetime
)
set nocount on
select #MaxRows = count(*) from #Import
-- Next new seed
select #stg_topseed = #stg_topseed + #optInterval
select #rc=0
while #RowCnt <= #MaxRows
begin
select #colu_Name = colu_Name from #Import where rownum = #RowCnt
select #colu_UPRN = colu_UPRN from #Import where rownum = #RowCnt
select #colu_JoinedOn = colu_JoinedOn from #Import where rownum = #RowCnt
set #Sql_string = 'update ' + #JvarTable + ' set ' + #varColumn + ' = ' + #stg_topseed + ' where Name = ''' + #colu_Name + ''' and UPRN = ''' + #colu_UPRN + ''' '
exec (#Sql_string)
select #stg_topseed = #stg_topseed + #optInterval
Select #RowCnt = #RowCnt + 1
end
print 'END'
end
Related
Drop and Create table if exist if not then Create in oracle Procedure
I have a query that takes start and end year for data also it takes a name of a table as procedure parameters.. the query then will create a table with that name if it doesn't exist or if exist it will drop and recreate it CREATE OR REPLACE Procedure USE_RAWDATA ( START_RP IN NUMBER, END_RP IN NUMBER,TABLE_NAME varchar) IS v_listStr CLOB; DAT VARCHAR(500):=to_char(to_date(SYSDATE), 'yyyymmdd'); cnt NUMBER; BEGIN BEGIN SELECT COUNT(*) INTO cnt FROM user_tables WHERE table_name = TABLE_NAME||'_'||DAT; dbms_output.put_line(TABLE_NAME||'_'||DAT); dbms_output.put_line(cnt); IF (cnt) = 1 THEN EXECUTE IMMEDIATE 'DROP TABLE '||TABLE_NAME||'_'||DAT; dbms_output.put_line('DROP TABLE '||TABLE_NAME||'_'||DAT); END IF; END; select rtrim(xmlagg(xmlelement(e,column_name,', ').extract('//text()') order by column_id).getclobval(),', ') x INTO v_listStr from RAW_DATA_METADATA WHERE (START_ROUND<= END_RP and END_ROUND is NULL) or (START_ROUND >= START_RP and END_ROUND <= END_RP ); EXECUTE IMMEDIATE 'CREATE TABLE '||TABLE_NAME||'_'||DAT||' AS SELECT '||v_listStr ||' FROM RAW_DATA WHERE ROUND_ID BETWEEN '||START_RP ||' AND '||END_RP; END; / my problem is that cnt is always giving me 0 even the table exists then the procedure will end with an error table already exist... I don't know why .. since when I try it as PL\SQL query it gives me a correct result cnt =1 if exist declare v_listStr CLOB; DAT VARCHAR(500):=to_char(to_date(SYSDATE), 'yyyymmdd'); cnt NUMBER; BEGIN BEGIN SELECT COUNT(*) INTO cnt FROM user_tables WHERE :TABLE_NAME = :TABLE_NAME||'_'||DAT; dbms_output.put_line(:TABLE_NAME||'_'||DAT); dbms_output.put_line(cnt); IF (cnt) = 1 THEN EXECUTE IMMEDIATE 'DROP TABLE '||:TABLE_NAME||'_'||DAT; dbms_output.put_line('DROP TABLE '||:TABLE_NAME||'_'||DAT); END IF; END; select rtrim(xmlagg(xmlelement(e,column_name,', ').extract('//text()') order by column_id).getclobval(),', ') x INTO v_listStr from RAW_DATA_METADATA WHERE (START_ROUND<= :END_RP and END_ROUND is NULL) or (START_ROUND >= :START_RP and END_ROUND <= :END_RP ); EXECUTE IMMEDIATE 'CREATE TABLE '||:TABLE_NAME||'_'||DAT||' AS SELECT '||v_listStr ||' FROM RAW_DATA WHERE ROUND_ID BETWEEN '||:START_RP ||' AND '||:END_RP; END; / can you help me figure out why it always cnt gives 0 even the table is exist
This query can only ever return 0: select count(*) into cnt from user_tables where table_name = table_name || '_' || dat; You need to either prefix table_name with the procedure name select count(*) into cnt from user_tables where table_name = use_rawdata.table_name || '_' || dat; or else name your parameters differently (tableName, p_table_name etc). I'd also suggest removing the first begin and end as they aren't doing anything, and adjusting your indentation to reflect the code structure more accurately. I make it something like this: create or replace procedure use_rawdata ( start_rp in number , end_rp in number , table_name varchar2 ) is v_liststr clob; dat varchar2(8) := to_char(sysdate, 'yyyymmdd'); cnt number; begin select count(*) into cnt from user_tables where table_name = upper(use_rawdata.table_name) || '_' || dat; dbms_output.put_line(table_name || '_' || dat); dbms_output.put_line(cnt); if cnt = 1 then execute immediate 'DROP TABLE ' || table_name || '_' || dat; dbms_output.put_line('DROP TABLE ' || table_name || '_' || dat); end if; select rtrim(xmlagg(xmlelement(e, column_name, ', ').extract('//text()') order by column_id).getclobval(), ', ') x into v_liststr from raw_data_metadata where (start_round <= end_rp and end_round is null) or (start_round >= start_rp and end_round <= end_rp); execute immediate 'create table ' || table_name || '_' || dat || ' as select ' || v_liststr || ' from raw_data where round_id between ' || start_rp || ' and ' || end_rp; end;
Passing in variables to SQL Server stored procedure, where clause
I am writing an application responsible for archiving data and we have the configuration in a database table Id | TableName | ColumnName | RetentionAmountInDays 1 | DeviceData | MetricTime | 3 So when faced with this configuration, I should archive all data in the DeviceData table where the MetricTime value is before 3 days ago. The reason I am doing this dynamically is the table names and column names differ (there would be multiple rows) For each configuration this stored procedure is called CREATE PROCEDURE GetDynamicDataForArchive #TableName nvarchar(100), #ColumnName nvarchar(100), #OlderThanDate datetime2(7) AS BEGIN SET NOCOUNT ON; DECLARE #sql nvarchar(1000); SET #sql = 'SELECT * FROM ' + #TableName + ' WHERE ' + #ColumnName + ' < #OlderThanDate'; exec sp_executesql #sql; END And an example exec line exec dbo.GetDynamicDataForArchive 'DeviceData', 'MetricTime', '2017-04-16 20:29:29.647' This results in: Conversion failed when converting date and/or time from character string. So something is up with how I am passing in the datetime2 or how I am forming the where clause.
Replace this statement: SET #sql = 'SELECT * FROM ' + #TableName + ' WHERE ' + #ColumnName + ' < #OlderThanDate' by SET #sql = 'SELECT * FROM ' + #TableName + ' WHERE [' + #ColumnName + '] < ''' + cast(#OlderThanDate as varchar(23)) + ''''; I don't particularly like having to convert the datetime to a varchar value though, perhaps there is a better way to do this(?).
Dynamic order by multiple columns in SQL Server
I use SQL Server 2012. I have a sample table named 'Table1' with seven columns. CREATE TABLE TABLE1 ( Field1 INT , Field2 INT , Field3 INT , Field4 INT , Field5 INT , Field6 INT , Field7 INT ) GO INSERT INTO TABLE1 VALUES (1,2,9,5,1,5,85) INSERT INTO TABLE1 VALUES (2,6,8,4,1,4,45) INSERT INTO TABLE1 VALUES (3,5,7,3,5,6,1) INSERT INTO TABLE1 VALUES (4,4,6,1,51,4,1) INSERT INTO TABLE1 VALUES (5,5,5,4,7,2,7) INSERT INTO TABLE1 VALUES (6,5,4,6,4,7,8) INSERT INTO TABLE1 VALUES (7,12,5,3,2,5,3) INSERT INTO TABLE1 VALUES (8,1,6,5,9,5,1) INSERT INTO TABLE1 VALUES (9,1,13,2,1,7,3) INSERT INTO TABLE1 VALUES (10,6,9,3,6,2,6) INSERT INTO TABLE1 VALUES (11,2,1,2,8,7,7) INSERT INTO TABLE1 VALUES (12,7,6,1,3,3,2) INSERT INTO TABLE1 VALUES (13,7,2,6,4,7,1) GO I have created the below Stored Procedure, This SP is able to query data considering the asked order by column. I can query my table with each possibility of single column and kind of order by (ASC or Desc). CREATE Procedure ProceName ( #OrderByField INT = 1, #OrderDirection INT = 0 -- 0 = Asc , 1 = Desc ) As Begin SELECT * FROM Table1 ORDER BY CASE WHEN #OrderDirection=0 AND #OrderByField=1 THEN Field1 END ASC, CASE WHEN #OrderDirection=0 AND #OrderByField=2 THEN Field2 END ASC, CASE WHEN #OrderDirection=0 AND #OrderByField=3 THEN Field3 END ASC, CASE WHEN #OrderDirection=0 AND #OrderByField=4 THEN Field4 END ASC, CASE WHEN #OrderDirection=0 AND #OrderByField=5 THEN Field5 END ASC, CASE WHEN #OrderDirection=0 AND #OrderByField=6 THEN Field6 END ASC, CASE WHEN #OrderDirection=0 AND #OrderByField=7 THEN Field7 END ASC, CASE WHEN #OrderDirection=1 AND #OrderByField=1 THEN Field1 END DESC, CASE WHEN #OrderDirection=1 AND #OrderByField=2 THEN Field2 END DESC, CASE WHEN #OrderDirection=1 AND #OrderByField=3 THEN Field3 END DESC, CASE WHEN #OrderDirection=1 AND #OrderByField=4 THEN Field4 END DESC, CASE WHEN #OrderDirection=1 AND #OrderByField=5 THEN Field5 END DESC, CASE WHEN #OrderDirection=1 AND #OrderByField=6 THEN Field6 END DESC, CASE WHEN #OrderDirection=1 AND #OrderByField=7 THEN Field7 END DESC End GO EXECUTE ProceName #OrderByField=1, #OrderDirection=0 EXECUTE ProceName #OrderByField=6, #OrderDirection=1 Now I need to change this sp for accepting multi columns as order by series columns. They can be pass by name or by order of columns. In this case i should be able to execute my SP like below command: EXECUTE ProceName #OrderByField='6,7,2', #OrderDirection='0,1,1' How can I achive this gool with out using the sp_executesql (Dynamic Query)?
Well, your ascending and descending wouldn't matter in your case unless you were trying to choose asc and desc for each column. Here is using the last column. DECLARE #OrderByField VARCHAR(64) = '1,3,7' DECLARE #DynamicColumns VARCHAR(256) = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#OrderByField,1,'FIELD1'),2,'FIELD2'),3,'FIELD3'),4,'FIELD4'),5,'FIELD5'),6,'FIELD6'),7,'FIELD7') DECLARE #OrderDirection INT = 1 DECLARE #order varchar(4) SET #order = CASE WHEN #OrderDirection = 1 THEN 'DESC' ELSE 'ASC' END --uncomment this line of code to add the sort to every column which only matters for DESC since ASC is default --SET #DynamicColumns = REPLACE(#DynamicColumns,',', ' ' + #order + ',') DECLARE #sql VARCHAR(MAX) = ( 'SELECT * FROM Table1 ORDER BY ' + #DynamicColumns + ' ' + #order) SELECT #sql EXEC(#sql)
CREATE Procedure ProceName ( #OrderByField VARCHAR(100), #OrderDirection VARCHAR(100), ) As Begin Declare #SQL VARCHAR(MAX) if OBJECT_ID('Example1') is not null begin drop table Example end if OBJECT_ID('Example2') is not null begin drop table Example2 end Create table Example1 ( id int identity(1,1), Field varchar(20) ) Create table Example2 ( id int identity(1,1), OrderNumber varchar(10) ) --iterate each element for both #OrderByField and #OrderDirection Declare #separator char(1)=',' Declare #position int = 0 Declare #name varchar(20) Set #OrderByField = #OrderByField + #separator --------------------------------------------------------------------------- /*iterate each for #OrderByField */ --------------------------------------------------------------------------- While CHARINDEX (#separator,#OrderByField,#position) != 0 BEGIN SET #name = SUBSTRING (#OrderByField,#position,CHARINDEX (#separator,#OrderByField,#position)-#position) SET #SQL = 'Insert into Example1([Field]) Values(' + char(39) + #name + char(39) + ')' EXEC(#SQL) SET #position = CHARINDEX(#separator,#OrderByField,#position)+1 END --------------------------------------------------------------------------- /*iterate each for #OrderDirection */ --------------------------------------------------------------------------- SET #position = 0 --do not forget to reset the position number Set #OrderDirection = #OrderDirection + #separator While CHARINDEX (#separator,#OrderDirection,#position) != 0 BEGIN SET #name = SUBSTRING (#OrderDirection,#position,CHARINDEX (#separator,#OrderDirection,#position)-#position) SET #SQL = 'Insert into Example2([OrderNumber]) Values(' + char(39) + #name + char(39)+ ')' EXEC(#SQL) SET #position = CHARINDEX(#separator,#OrderDirection,#position)+1 END Set #name = '' --reset the #name for the use of Cursor declare #NewName varchar(500) ='' Declare row_cursor CURSOR FOR select 'Field'+a.Field + ' '+ case when b.OrderNumber = 0 then 'ASC' else 'DESC' end +',' as command from Example1 as a inner join Example2 as b on b.id = a.id OPEN row_cursor FETCH NEXT FROM row_cursor into #name WHILE (##FETCH_STATUS =0) begin Set #NewName = #NewName + #name FETCH NEXT FROM row_cursor into #name end close row_cursor deallocate row_cursor SET #NewName = REVERSE(STUFF(REVERSE(#NewName),1,1,'')) SET #SQL = 'Select * From Table1 Order by ' + #NewName --Print(#SQL) EXEC (#SQL) END
IBM DB2 Equivalent syntax for SQL Server Stored Procedure - error while deploying
I am newbie to IBM db2.Need to convert the below mentioned SP to db2 syntax. But i am stuck with many equivalents used or available in Db2. Even google research doesn't show how exactly we can compare object id of tables in db2 as I am doing in SQL Server stored procedure. Could anyone suggest me with right way to proceed? EDIT: I have updated with equivalent DB2 syntax, but facing below error while deploying at the particular line, Can anyone identify and help me understand what is wrong with this syntax or the problem lies anywhere else in the procedure. line no 25 : DECLARE v_sqlstate CHAR(5); BACKUPTABLE: 25: An unexpected token "<variable declaration> was found following "". Expected tokens may include: "".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.18.60 An unexpected token variable declaration was found following "". Expected tokens may include: "".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.18.60 SQL Server Stored procedure syntax: CREATE PROCEDURE [dbo].[BackUpTable] #TableName sysname AS BEGIN SET nocount ON DECLARE #sql VARCHAR(500) IF EXISTS (SELECT * FROM sys.objects WHERE object_id = Object_id(N'[dbo].[' + #TableName+'_EST' + ']') AND TYPE IN ( N'U' )) BEGIN SET #sql = 'declare #Done bit set #Done = 0 while #Done = 0 begin delete top (100000) from ' + #TableName + '_Bak' + ' if ##rowcount = 0 set #Done = 1 end;' SET #sql = #sql + 'insert into ' + #TableName + '_Bak select * from ' + #TableName +'_EST' EXEC(#sql) END ELSE BEGIN DECLARE #err_message VARCHAR(300) SELECT #err_message = 'The table "' + Isnull(#TableName, 'null') + '" does not exist' RAISERROR (#err_message, 16, 1) END END DB2 SYNTAX CREATED SO FAR: CREATE OR REPLACE PROCEDURE BackUpTable (IN TableName VARCHAR(128)) DYNAMIC RESULT SETS 1 BEGIN DECLARE dynamicSql VARCHAR(500); IF(EXISTS( SELECT * FROM SYSIBM.SYSTABLES WHERE NAME = TableName||'_EST' ) ) THEN SET dynamicSql = 'DELETE FROM '||TableName ||'_BAK'; SET dynamicSql = dynamicSql ||'insert into ' || TableName || '_BAK select * from ' || TableName || '_EST'; EXECUTE IMMEDIATE dynamicSql; ELSE DECLARE v_sqlstate CHAR(5); DECLARE v_sqlcode INT; DECLARE SQLSTATE CHAR(5) DEFAULT '00000'; DECLARE SQLCODE INT DEFAULT 0; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN SELECT SQLSTATE, SQLCODE INTO v_sqlstate, v_sqlcode FROM sysibm.sysdummy1; SET O_Error_Msg = 'TABLE IS NOT AVAILABLE:: SQLState : '||v_sqlstate||' SQLCode : '||v_sqlcode ; END; END IF; END
on z/os you can do it: IF( EXISTS( SELECT 1 FROM QSYS2.SYSTABLES WHERE TABLE_SCHEMA = 'YOURLIB' AND TABLE_NAME = 'YOURTABLENAME')) THEN DROP TABLE YOURLIB.YOURTABLENAME; END IF;
How to get user name who updated the data from UI in MVC 5 and Entity Framework
We have a website in ASP.NET MVC 5 with Entity Framework. When a logged in user made changes in UI (i.e. update the data) we save/update/delete the data in SQL Server as per operation performed by the user. We also have a trigger for audit trailing. With the trigger, table format for storing data is as below: [AuditID] [Type] -- Contains operation performed (Insert (I), Update (U), Delete (D)) [TableName] [PK] -- Primary Key [FieldName] [OldValue] [NewValue] [UpdateDate] [UserName] We are storing SYSTEM_USER in [UserName] column. If we have any solution to store the [UserName] who actually made changes from UI instead of system_user? Do we have any approach to pass [UserName] from application (UI) to the trigger? Please share your thoughts. I have one solution - to add UpdatedBy column name in all the tables so that trigger can easily get the value of UpdatedBy column from magic tables or from main tables. Please suggest best approach. Below is the trigger used. CREATE TRIGGER [ids].[tr_AuditEmploee] ON Employee FOR INSERT, UPDATE, DELETE AS DECLARE #bit INT, #field INT, #maxfield INT, #char INT, #fieldname VARCHAR(128), #TableName VARCHAR(128), #PKCols VARCHAR(1000), #sql VARCHAR(2000), #UpdateDate VARCHAR(21), #UserName VARCHAR(128), #Type CHAR(1), #PKSelect VARCHAR(1000) --You will need to change #TableName to match the table to be audited SELECT #TableName = 'Employee' -- date and user SELECT #UserName = SYSTEM_USER, #UpdateDate = CONVERT(VARCHAR(8), GETDATE(), 112) + ' ' + CONVERT(VARCHAR(12), GETDATE(), 114) -- Action IF EXISTS (SELECT * FROM inserted) IF EXISTS (SELECT * FROM deleted) SELECT #Type = 'U' ELSE SELECT #Type = 'I' ELSE SELECT #Type = 'D' -- get list of columns SELECT * INTO #ins FROM inserted SELECT * INTO #del FROM deleted -- Get primary key columns for full outer join SELECT #PKCols = COALESCE(#PKCols + ' and', ' on') + ' i.' + c.COLUMN_NAME + ' = d.' + c.COLUMN_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk, INFORMATION_SCHEMA.KEY_COLUMN_USAGE c WHERE pk.TABLE_NAME = #TableName AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND c.TABLE_NAME = pk.TABLE_NAME AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME -- Get primary key select for insert SELECT #PKSelect = COALESCE(#PKSelect+'+','') + '''' + COLUMN_NAME + '=''+convert(varchar(100), coalesce(i.' + COLUMN_NAME +', d.' + COLUMN_NAME + '))+''''' FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk , INFORMATION_SCHEMA.KEY_COLUMN_USAGE c WHERE pk.TABLE_NAME = #TableName AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND c.TABLE_NAME = pk.TABLE_NAME AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME IF #PKCols IS NULL BEGIN RAISERROR('no PK on table %s', 16, -1, #TableName) RETURN END SELECT #field = 0, #maxfield = MAX(ORDINAL_POSITION) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #TableName WHILE #field < #maxfield BEGIN SELECT #field = MIN(ORDINAL_POSITION) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #TableName AND ORDINAL_POSITION > #field SELECT #bit = (#field - 1 )% 8 + 1 SELECT #bit = POWER(2,#bit - 1) SELECT #char = ((#field - 1) / 8) + 1 IF SUBSTRING(COLUMNS_UPDATED(),#char, 1) & #bit > 0 OR #Type IN ('I','D') BEGIN SELECT #fieldname = COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #TableName AND ORDINAL_POSITION = #field SELECT #sql = ' insert [audit].[AuditEmployee] ( Type, TableName, PK, FieldName, OldValue, NewValue, UpdateDate, UserName) select ''' + #Type + ''',''' + #TableName + ''',' + #PKSelect + ',''' + #fieldname + '''' + ',convert(varchar(1000),d.' + #fieldname + ')' + ',convert(varchar(1000),i.' + #fieldname + ')' + ',''' + #UpdateDate + '''' + ',''' + #UserName + '''' + ' from #ins i full outer join #del d' + #PKCols + ' where i.' + #fieldname + ' <> d.' + #fieldname + ' or (i.' + #fieldname + ' is null and d.' + #fieldname + ' is not null)' + ' or (i.' + #fieldname + ' is not null and d.' + #fieldname + ' is null)' EXEC (#sql) END END