I have created a stored procedure in Sybase using interactive sql which compares two rows from two tables with same structure and if there is any difference in any column's data of the table then it returns that particular row.
Stored procedure is written as below:
CREATE or replace PROCEDURE Validation
#databaseTo SYSNAME,
#tableTo SYSNAME,
#tableFrom SYSNAME
AS
BEGIN
DECLARE #stmt NVARCHAR(10000)
DECLARE #columnName VARCHAR(100)
DECLARE #nameList VARCHAR(8000)
select #nameList=""
select #stmt=""
select #columnName=""
SET NOCOUNT ON
DECLARE c1 cursor
for select name
from syscolumns
where id=(select id
from sysobjects
where name=#tableFrom)
OPEN c1
FETCH c1
INTO #columnName
while( ##sqlstatus!=2)
BEGIN
if(#columnName!= "rqst_id")
BEGIN
select #nameList=#nameList+"a."+#columnName+"= b."+#columnName+" AND "
END
FETCH c1
INTO #columnName
END
close c1
select #nameList=#nameList+"a.rqst_id=b.rqst_id"
PRINT #nameList
PRINT #tableFrom
select #stmt='select a.* from '+ #tableFrom+' a LEFT JOIN '+ #databaseTo+'.dbo.'+#tableTo+' b on '+ #nameList+' where b.rqst_id IS NULL'
PRINT #stmt
EXEC #stmt
END
this stored procedure compiles properly but when executed using below statement
EXEC dbo.Validation ('fr2015_dev','fr300output_cost','fr300output_cost')
I get this error
"Couldn't execute statement
Stored procedure 'select a.* from fr300output_cost a LEFT JOIN fr2015_dev.dbo.fr300output_cost b on a.carrier_id= b.carrier_id AND
a.rec_num= b.rec_num AND a.amenity_cost= b.amenity_cost AND
a.circuity_cost= b.circuity_cost AND a.lost_utilization_cost=
b.lost_utilization_cost AND a.dest_fuel_cost= b.dest_fuel_cost AND
a.future_stop_cost= b.future_stop_cost AND a.s' not found.
...
sp_help may produce lots of outputs.
sybase error code 2812"
I see this proc on running 'sp_help'.Please help me solving this problem .
This way
EXEC #stmt
you run a procedure so this the reason for your error.
For run dynamic sql you have to use parenthesis as below
EXEC (#stmt)
your full code should be
CREATE or replace PROCEDURE Validation
#databaseTo SYSNAME,
#tableTo SYSNAME,
#tableFrom SYSNAME
AS
BEGIN
DECLARE #stmt NVARCHAR(10000)
DECLARE #columnName VARCHAR(100)
DECLARE #nameList VARCHAR(8000)
select #nameList=""
select #stmt=""
select #columnName=""
SET NOCOUNT ON
DECLARE c1 cursor
for select name
from syscolumns
where id=(select id
from sysobjects
where name=#tableFrom)
OPEN c1
FETCH c1
INTO #columnName
while( ##sqlstatus!=2)
BEGIN
if(#columnName!= "rqst_id")
BEGIN
select #nameList=#nameList+"a."+#columnName+"= b."+#columnName+" AND "
END
FETCH c1
INTO #columnName
END
close c1
select #nameList=#nameList+"a.rqst_id=b.rqst_id"
PRINT #nameList
PRINT #tableFrom
select #stmt='select a.* from '+ #tableFrom+' a LEFT JOIN '+ #databaseTo+'.dbo.'+#tableTo+' b on '+ #nameList+' where b.rqst_id IS NULL'
PRINT #stmt
EXEC (#stmt)
END
Related
I want to create a stored procedure that will update a table. The procedure will join two tables and I want to pass the table name using a variable (#tablename).
This error is generated:
Must declare the table variable "#tablename".
My code:
Create Procedure dbo.SpUpdate (#TableName varchar(50))
as
begin
set #tablename='Customer'
Update a
Set AgentNumber = '5',
From dbo.CustomerList a
join #tablename b on a.customerid = b.customerid
end
You can use this script:
Create Procedure dbo.SpUpdate (#TableName varchar(50))
as
begin
DECLARE #SqlText NVARCHAR(MAX)
SET #SqlText =
'Update a
Set AgentNumber=''5'',
From dbo.CustomerList a
join ' + QUOTENAME(#tablename) + ' b
on a.customerid= b.customerid'
EXEC sp_executesql #SqlText
end
If I run the select statement below by itself (with the table name hard coded in) it runs fine and the temp table is created. If I run it as below it says 'Invalid object name '#TempCodes'' although when I print #Sql1 it looks exactly the same as when I run it by itself (with the table name hard coded in).
Any ideas on what's going on here will be appreciated.
DECLARE #TableName NVARCHAR(50)
SET #TableName = '[My Table Name]'
DECLARE #Sql1 NVARCHAR(MAX);
SET #Sql1 = N'SELECT AccountNumber,LTRIM(RTRIM(m.n.value(''.[1]'',''varchar(8000)''))) AS mdcodes INTO #TempCodes FROM (SELECT AccountNumber,CAST(''<XMLRoot><RowData>''
+ REPLACE(MD_Results,'','',''</RowData><RowData>'')
+ ''</RowData></XMLRoot>'' AS XML) AS x FROM ' + #TableName
+ N')t CROSS APPLY x.nodes(''/XMLRoot/RowData'')m(n)'
IF OBJECT_ID('tempdb.dbo.#TempCodes', 'U') IS NOT NULL
BEGIN
drop table #TempCodes
END
EXECUTE sp_executesql #Sql1
Select * from #TempCodes
I believe ## is a typo. Even if you fix it to # it will throw same error.
EXECUTE sp_executesql #Sql1
A local temporary table created in a stored procedure is dropped
automatically when the stored procedure is finished.
In your case sp_executesql is the stored procedure.
the table created inside the dynamic query will be dropped after the exec sp_executesql is completed. That's why you are getting that error.
You need to create table outside and use Insert into table..select syntax inside the dynamic query
IF OBJECT_ID('tempdb.dbo.#TempCodes', 'U') IS NOT NULL
drop table #TempCodes
create table #TempCodes(AccountNumber varchar(100),mdcodes varchar(100))
SET #Sql1 = N'Insert into #TempCodes
SELECT AccountNumber,LTRIM(RTRIM(m.n.value(''.
[1]'',''varchar(8000)''))) AS mdcodes FROM (SELECT
AccountNumber,CAST(''<XMLRoot><RowData>'' +
REPLACE(MD_Results,'','',''</RowData><RowData>'') + ''</RowData></XMLRoot>''
AS XML) AS x FROM '+#TableName+ N')t CROSS APPLY
x.nodes(''/XMLRoot/RowData'')m(n)'
Try using a global temp table ##TempCodes as local temporary tables are only visible in current session.
DECLARE #TableName NVARCHAR(50)
SET #TableName = '[My Table Name]'
DECLARE #Sql1 NVARCHAR(MAX);
SET #Sql1 = N'SELECT AccountNumber,LTRIM(RTRIM(m.n.value(''.
[1]'',''varchar(8000)''))) AS mdcodes INTO ##TempCodes FROM (SELECT
AccountNumber,CAST(''<XMLRoot><RowData>'' +
REPLACE(MD_Results,'','',''</RowData><RowData>'') + ''</RowData></XMLRoot>''
AS XML) AS x FROM '+#TableName+ N')t CROSS APPLY
x.nodes(''/XMLRoot/RowData'')m(n)'
IF OBJECT_ID('tempdb.dbo.##TempCodes', 'U') IS NOT NULL
BEGIN
drop table ##TempCodes
END
EXECUTE sp_executesql #Sql1
Select * from ##TempCodes
I did this. But unfortunately that return all in many table. I want to return all in one unique table. Maybe using "UNION" but I don't know the way to do.
This is my code:
EXEC sp_msforeachdb 'select ''?''AS "DataBase", s.name, t.name AS "Tables",max(si.rows) as "Rows Line"
from [?].sys.tables t inner join [?].sys.schemas s
on t.schema_id = s.schema_id
inner join [?].sys.partitions si on t.object_id = si.object_id
where t.name like "%ATTACH" group by s.name,t.name'`
You cannot do it in a single query.
You could query the sys.databases table to get a temporary table of all your databases, and then run a dynamic query on each database to store the results of the query in your question all in another temporary table.
Then at the end, you just select all rows from the last temporary table.
I have found finally a solution.i just used a Stored Procedures for having the result i was looking for.So decided to post the answer here maybe that will help someone else.
DECLARE #banco_nome nvarchar(MAX), #tabela_nome nvarchar(MAX)
DECLARE #banco_cursor CURSOR
DECLARE #sqlstatement nvarchar(MAX)
DECLARE #count_sql nvarchar(MAX)
DECLARE #total int
DECLARE #RegistrosFotograficos TABLE
(
DatabaseName nvarchar(max),
TableName nvarchar(max),
Total int
)
SET #banco_cursor = CURSOR FORWARD_ONLY FOR
SELECT name FROM sys.databases
OPEN #banco_cursor
FETCH NEXT FROM #banco_cursor INTO #banco_nome
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlstatement = 'DECLARE tabela_cursor CURSOR FORWARD_ONLY FOR SELECT TABLE_NAME FROM ' + #banco_nome + '.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''BASE TABLE'' AND TABLE_NAME LIKE ''%ATTACH'' ORDER BY TABLE_NAME'
EXEC sp_executesql #sqlstatement
OPEN tabela_cursor
FETCH NEXT FROM tabela_cursor INTO #tabela_nome
WHILE ##FETCH_STATUS = 0
BEGIN
SET #count_sql = 'USE ' + #banco_nome + '; SELECT #total=COUNT(1) FROM ' + #tabela_nome;
EXECUTE sp_executesql #count_sql, N'#total int OUTPUT', #total=#total OUTPUT
INSERT INTO #RegistrosFotograficos (DatabaseName, TableName, Total) VALUES (#banco_nome, #tabela_nome, #total);
FETCH NEXT FROM tabela_cursor INTO #tabela_nome
END
CLOSE tabela_cursor;
DEALLOCATE tabela_cursor;
FETCH NEXT FROM #banco_cursor INTO #banco_nome
END
CLOSE #banco_cursor;
DEALLOCATE #banco_cursor;
SELECT * FROM #RegistrosFotograficos
This will list all the tables in a given database and the number of rows in each. Notice the results are in a table named #results:
set nocount on
declare #curtable sysname
declare #prevtable sysname
declare #curcount int
declare #tsql varchar(500)
if object_ID('tempdb..#curtables','U') is not null
drop table #curtables
select name into #curtables
from sys.objects
where type='U'
order by 1
if object_id('tempdb..#results','U') is not null
drop table #results
create table #results(name sysname,numrows int)
select top 1 #curtable=name from #curtables order by name
while (1=1)
begin
set #tsql = 'select '''+quotename(#curtable) +''',count(*) numrows from '+quotename(#curtable)
print #tsql
insert into #results
exec (#tsql)
set #prevtable= #curtable
select top 1 #curtable = name
from #curtables
where name > #prevtable
order by name
if #curtable=#prevtable
break
end
I am trying to run this procedure in order to select a bunch of results from multiple tables in another databases and put everything into one temp table. I can only use this one stored procedure and can't put it into another database
I tried using this here, but it didn't work and gave me the error
'Must declare the scalar variable "#lcsqlcmd"'. #lcsqlcmd
I already declared though any help?
EXEC master..sp_MSforeachdb
IF DB_ID(''?'') > 4
BEGIN
INSERT INTO #TempTable
EXECUTE (#lcsqlcmd)
END
The easiest way is to build the actual T-SQL string you want to run on each database and execute that. The other databases have no knowledge of the stored procedure you are trying to run.
The proper syntax in your case would be something like this.
CREATE TABLE #TempTable( [DBID] INT, DBName SYSNAME )
DECLARE #ForEachCommand VARCHAR( MAX ), #lcsqlcmd VARCHAR( MAX )
SET #lcsqlcmd = 'USE [?]; SELECT DB_ID() AS [DBID], DB_NAME( DB_ID()) AS DBName'
SET #ForEachCommand =
'IF DB_ID(''?'') > 4
BEGIN
insert into #TempTable
EXEC sp_executesql N''' + #lcsqlcmd + '''
end'
print #ForEachCommand
EXECUTE master.sys.sp_MSforeachdb #ForEachCommand
SELECT * FROM #TempTable
See: http://weblogs.sqlteam.com/joew/archive/2008/08/27/60700.aspx
Note: generally it is not a good idea to build your code around undocumented procedures.
The code that does not use undocumented procedure is below:
SELECT database_id, name AS DBName
INTO #Databases
FROM sys.databases WHERE database_id > 4
CREATE TABLE #TempTable( [DBID] INT, DBName SYSNAME )
DECLARE #lcsqlcmd NVARCHAR( MAX ), #Command NVARCHAR( MAX )
SET #lcsqlcmd = 'USE [?]; SELECT DB_ID() AS [DBID], DB_NAME( DB_ID()) AS DBName'
DECLARE #DBName SYSNAME
SET #DBName = ( SELECT TOP 1 DBName FROM #Databases ORDER BY DBName )
WHILE NOT #DBName IS NULL
BEGIN
SET #Command = REPLACE( #lcsqlcmd, '?', #DBName )
insert into #TempTable
EXEC sp_executesql #Command
SET #DBName = ( SELECT TOP 1 DBName FROM #Databases WHERE DBName > #DBName ORDER BY DBName )
END
SELECT * FROM #TempTable
DROP TABLE #Databases
I have written this procedure,
DECLARE CURS_TABLE CURSOR FOR
SELECT NAME FROM SYS.TABLES WHERE NAME LIKE 'AK_LIB_ADDRESS'
DECLARE #TABLE_NAME VARCHAR(100);
DECLARE #SQL VARCHAR(300);
OPEN CURS_TABLE
FETCH NEXT FROM CURS_TABLE INTO #TABLE_NAME;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'ALTER TABLE '+#TABLE_NAME+' ADD PRIMARY KEY(ID);';
EXEC (#SQL)
FETCH NEXT FROM CURS_TABLE INTO #TABLE_NAME
END
CLOSE CURS_TABLE;
DEALLOCATE CURS_TABLE;
The problem is the exec(#sql) executing the same statement twice, i checked by placing print statement,it's working fine with print statement if i comment exec line...
So please can u give me any idea where i'm doing wrong..?
You should do like this, used a temporary table instead of selecting directly from the sys.tables
SELECT NAME into #temp FROM SYS.TABLES WHERE NAME LIKE 'AK_LIB_ADDRESS%'
DECLARE CURS_TABLE CURSOR FOR
SELECT NAME from #temp
DECLARE #TABLE_NAME VARCHAR(100);
DECLARE #SQL VARCHAR(300);
OPEN CURS_TABLE
FETCH NEXT FROM CURS_TABLE INTO #TABLE_NAME;
WHILE ##FETCH_STATUS = 0
BEGIN
select #TABLE_NAME
SET #SQL = 'ALTER TABLE '+#TABLE_NAME+' ADD PRIMARY KEY(ID);';
EXEC (#SQL)
FETCH NEXT FROM CURS_TABLE INTO #TABLE_NAME
END
CLOSE CURS_TABLE;
DEALLOCATE CURS_TABLE;
Or add a Insensitive keyword to the cursor. The reason is that you are changing a heap to the B-tree inside the trigger, that's the reason you are getting inconsistent behaviour in the cursor.
DECLARE CURS_TABLE CURSOR INSENSITIVE FOR
SELECT NAME FROM SYS.TABLES WHERE NAME LIKE 'AK_LIB_ADDRESS%'
DECLARE #TABLE_NAME VARCHAR(100);
DECLARE #SQL VARCHAR(300);