Before you say me,
I put retainsameconnection, I had put.
and I have delay validation on ALL my components too
after in others query where I use this dynamic temp table
this fails (sometimes) saying temp table does not exist.
How can I solve it?
This is my query..
declare #usuario varchar(100)
declare #contra varchar(100)
declare #servidor varchar(100)
declare #based varchar(100)
declare #nombretabla varchar(100)
set #usuario ='pruebas'
set #contra ='123'
set #servidor ='1.6.7.9'
set #based ='op'
set #nombretabla='tablaBC245B7A910D4B488CC9EFF0EFD3C177'
/*this was a dynamic name got with this query in other execute sql task
declare #tabla varchar(50)
set #tabla=NEWID ()
set #tabla =REPLACE (#tabla ,'-','')
select 'tabla'+#tabla nombre
*/
declare #cadena varchar(500)
set #cadena ='SERVER='+#servidor+';DataBasE='+#based +
';uid='+#usuario +';pwd='+#contra+';'
set #cadena =''''+#cadena +''''
while OBJECT_ID('tempdb..##envases'+#nombretabla) IS NULL
begin
exec('
SELECT * into ##envases'+#nombretabla+'
FROM OPENROWSET(
''SQLNCLI'',
'+#cadena+',
''
select pro=p.pro,envase=e.pro from procorp p
join procorp e on p.envase=e.envase and e.esenvase=1
union all select pro=-1,envase=-1
'')
'
)
end
IF OBJECT_ID('tempdb..#primera') IS NOT NULL DROP TABLE #primera
IF OBJECT_ID('tempdb..#end') IS NOT NULL DROP TABLE #end
create table #primera(
pro int,
envase int
)
insert into #primera
exec('select * from ##envases'+#nombretabla+'')
select fila='select pro='+CONVERT(varchar(10),pro)+
', envase='+CONVERT(varchar(10),envase)+' union all '
into #end
from #primera
--select * from #end
--drop table #end
--drop table #primera
alter table #end
add
uno int not null default(1),
id int identity
declare #maximo int
set #maximo =(select MAX(id) from #end )
update #end set fila=fila+'terminado' where id=#maximo
update #end set fila=replace(fila,'union all terminado','') where id=#maximo
select uno, ' begin try drop table #tmpenvase end try begin catch end catch
select * into #tmpenvase from ( '+
convert(varchar(max),STUFF(
(select '', convert(varchar(max),fila) from #end order by id
for xml path('') )
,1,0,'') )+' ) q 'cadena
from #end e
group by uno
I would use standard SSIS objects for this.
I cant really follow what the end objective of your script is, but generally:
Connection strings can be managed using Configuration files, Variables and other means.
Within Data Flow Tasks, OLE DB Source Transformations can run SELECT statements, OLE DB Destinations can deliver data, OLE DB Commands can run UPDATE statements.
I would reimagine your requirements in terms of a series of tasks, rather than trying to force everything into a single T-SQL script.
Global temporary tables are visible to any user and any connection after they are created, and are deleted when all users that are referencing the table disconnect from the instance of SQL Server.
According to that paragraph of SQL Server Books-Online; as soon as SQL Server don't found any connection to a global temporary tables those temporary tables will deleted, and when you are create a local temporary table with EXEC command SQL Server will delete that local temporary table this will also applied to a global temporary table but after a checking for all users connections and so on. I think sometimes SQL Server found your global temporary table alone before the your next statement commits.
I suggest you to use local table variables and use INSERT EXEC to fill them.
And also there are some other ways too.
Related
I have a problem that works in SQL Server 2017 but not in SQL Server 2019. It is related to tempdb caching. This has to do with creating temporary tables in stored procedures and changing its structure using dynamic SQL. We have a need to do that for various dynamic reporting needs. The first time it is called, the structure is cached and subsequent call to the procedure fails or returns invalid results. How do I prevent caching of such tables? Below is some sample code and how come it works in 2017. Help appreciated.
CREATE PROCEDURE [dbo].[tempDBCachingCheck]
#yearList varchar(max)
AS
BEGIN
SET NOCOUNT ON
DECLARE #yearCount int
DECLARE #yearCounter INT
DECLARE #yearValue INT
DECLARE #sql nvarchar(max)
-- With table variable
DECLARE #tempYearList TABLE (id INT IDENTITY(1,1), rpt_yr int)
INSERT INTO #tempYearList (rpt_yr)
SELECT value FROM STRING_SPLIT(#yearList, ',');
SELECT * FROM #tempYearList
--------------------------------------------------------------------
--With temporary table, since we will be altering this with dynamic sql
CREATE TABLE #returnTable (id INT IDENTITY(1,1))
-- Tried adding a named constraint to not make it cache, but does not work
ALTER TABLE #returnTable
ADD CONSTRAINT UC_ID UNIQUE (id);
SELECT #yearCount = COUNT(*) FROM #tempYearList
-- Add the years as columns to the return table to demostrate the problem
SET #sql = N'ALTER TABLE #returnTable ADD '
SET #yearCounter = 1
WHILE #yearCounter <= #yearCount
BEGIN
SELECT #yearValue = rpt_yr FROM #tempYearList WHERE id = #yearCounter
IF #yearCounter > 1
SET #Sql = #Sql + N', '
SET #sql = #sql + N' [' + convert(varchar(20), #yearValue) + N'] float'
SET #yearCounter = #yearCounter + 1
END
EXECUTE sp_executesql #sql
SELECT * FROM #returnTable
-- No need to drop the temporary tables but doing just in case
DROP TABLE #returnTable
END
GO
-- run these statements and you will see the second call with return the cached #returnTable
EXEC tempDBCachingCheck '2019,2020'
EXEC tempDBCachingCheck '2017,2018,2019,2020'
GO
-- Clear temp table cache and call in reverse order, then will hit an error
-- 'A severe error occurred on the current command. The results, if any, should be discarded.'
USE tempDB
GO
DBCC FREEPROCCACHE
GO
EXEC tempDBCachingCheck '2017,2018,2019,2020'
EXEC tempDBCachingCheck '2019,2020'
GO
It seems this has been fixed in one of cummulative update. The description seems to match:
KB4538853:
When you repeatedly run a stored procedure that uses temporary table with indexes on SQL Server 2019, the client may receive an unexpected error with message "A severe error occurred on the current command" and an access violation exception is recorded on the SQL Server. If the same workload is executed on any previous major version of SQL Server, this issue does not occur.
Dan Guzman's recommendation to install newest CU is the way to go.
Using: EXEC tempDBCachingCheck '2017,2018,2019,2020' WITH RECOMPILE could help as well.
I am currently working on getting a set of records from a view in the Oracle database and trying to insert/update them in to the table in the SQL Server table depending on a column using BizTalk.
For this I created a stored procedure:
Create PROCEDURE [dbo].[uspInsertorUpdateDepartment]
#dept_name varchar(64),
#jax_dept_id char(32)
AS
BEGIN
SET NOCOUNT ON;
IF (SELECT TOP (1) 1 FROM afm.[jax_dept]
WHERE jax_dept_id = #jax_dept_id) IS NULL
INSERT INTO afm.[jax_dept](dept_name, jax_dept_id)
VALUES (#dept_name,#jax_dept_id)
ELSE
UPDATE afm.[jax_dept]
SET dept_name = #dept_name
WHERE jax_dept_id = #jax_dept_id
END
I created the schema for the stored procedure using consume adapter service. Used them in the mapping and the orchestration. Though I was not able to use the lopping functoid in the mapping
So removed the lopping and deployed the application. And tried to run and it ran without any error but just insert the first record from the oracle view in to the SQL Server database leaving all the other records. How can this be approached so the entire set of records from the oracle is inserted/updated in to SQL Server database.
Here I converted the separate update and insert into one merge statement:
Create PROCEDURE [dbo].[uspInsertorUpdateDepartment]
#dept_name varchar(64),
#jax_dept_id char(32)
AS
BEGIN
SET NOCOUNT ON;
merge afm.[jax_dept] as target
using (select #dept_name as dept_name, #jax_dept_id as jax_dept_id) as source
on source.jax_dept_id = target.jax_dept_id
when matched then
update target
SET dept_name = #dept_name
when not matched then
insert (dept_name, jax_dept_id)
values (#dept_name,#jax_dept_id)
;
END
Use table type as a parameter for the SP, instead of passing individually. We can
use looping functoid if we use User Defined Table value as a parameter.
CREATE TYPE dbo.SampleType AS TABLE
(
dept_name varchar(64) not null,
jax_dept_id char(32) not null
)
---
Create PROCEDURE [dbo].[uspInsertorUpdateDepartment]
#TVP dbo.SampleType READONLY
AS
BEGIN
SET NOCOUNT ON;
--your insert or update query
For more infor on how to use table value parameter check out this link:-
https://learn.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine
I need to write a report in SSRS (T-SQL) that shows any current user which reports on the SSRS report server they have read-access to, which is determined by Active Directory at the present. To complicate matters, the Active Directory doesn't have groups set up as group elements - all users in the AD are objectClass=User and objectCategory=Person.
My question is: how can I write a query that will match a user to all their "memberOf" elements without knowing necessarily what the group names are (since they might change, etc.)? From there, I think I can piece together how to match each element to the reports.
EDIT: Here's what I have written so far. It's not creating the procedure because of a syntax error, but I can't spot the error.
USE [ReportServer]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[ActiveDirectoryPermissions]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Table1 TABLE
(
[GroupName] nvarchar(MAX),
[GroupPath] nvarchar(MAX)
)
INSERT INTO #Table1 ( [GroupName], [GroupPath] )
SELECT sAMAccountName as [GroupName], replace(ADsPath,'LDAP://','') as [GroupPath]
FROM OPENQUERY( ADSI,
'SELECT sAMAccountname, ADsPath
FROM ''LDAP://DC=[REDACTED],DC=COM''
WHERE objectCategory=''group'' AND CN=''*''
ORDER BY CN')
DECLARE #Table2 TABLE
(
[GroupPath] nvarchar(MAX),
[MemberName] nvarchar(MAX)
)
DECLARE table_1_cursor CURSOR FOR
SELECT GroupPath
FROM #Table1 t1
DECLARE #SQL nvarchar(MAX)
DECLARE #temp nvarchar(MAX)
OPEN table_1_cursor
FETCH NEXT FROM table_1_cursor INTO #temp
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'SELECT '''+#temp+''' AS GroupPath, cn
FROM OPENQUERY(ADSI,
''SELECT cn
FROM ''''LDAP://DC=[REDACTED],DC=com''''
WHERE
memberOf='''''+#temp+'''''
'')'
INSERT INTO #Table2 ( [GroupPath], [MemberName] )
EXEC sp_executesql #SQL;
FETCH NEXT FROM table_1_cursor INTO #temp
END
CLOSE table_1_cursor
DEALLOCATE table_1_cursor
SELECT *
FROM #Table2 t2
INNER JOIN #Table1 t1 ON (t2.GroupPath=t1.GroupPath)
GO
Comment out the contents of the stored procedure and create it. Then alter the sproc by uncommenting the statements one at a time. You can also try commenting out parts of the select statement. I suspect the problem is where you are building # sql. I would select # temp and # sql at this point. Running the code directly rather than as part of a a procedure. That way you can manually check and test the output. Well done for persevering this far. Those ' would have driven me mad.
You are missing the final END on the stored procedure. Next problem: What is ADSI ? I presume that is the name of a linked server that exposes AD? As in
https://www.mssqltips.com/sqlservertip/2580/querying-active-directory-data-from-sql-server/
There is an alternative method of accessing AD that does not require the linked server.
EXEC master.dbo.sp_QueryAD
'SELECT sAMAccountname, ADsPath
FROM ''LDAP://OU=REDACTED,DC=REDACTED''
WHERE objectCategory=''group'' AND CN=''*''
ORDER BY CN'
There is a small amount of config to enable this, but if you search on the error, it only takes a moment to set up.
I have to create a stored procedure where I will pass tableName, columnName, id as parameters. The task is to select records from the passed table where columnName has passed id. If record is found update records with some fixed data. Also implement Transaction so that we can rollback in case of any error.
There are hundreds of table in database and each table has different schema that is why I have to pass columnName.
Don't know what is the best approach for this. I am trying select records into a temp table so that I can manipulate it as per requirement but its not working.
I am using this code:
ALTER PROCEDURE [dbo].[GetRecordsFromTable]
#tblName nvarchar(128),
#keyCol varchar(100),
#key int = 0
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
--DROP TABLE #TempTable;
DECLARE #sqlQuery nvarchar(4000);
SET #sqlQuery = 'SELECT * FROM ' + #tblName + ' WHERE ' + #keyCol + ' = 2';
PRINT #sqlQuery;
INSERT INTO #TempTable
EXEC sp_executesql #sqlQuery,
N'#keyCol varchar(100), #key int', #keyCol, #key;
SELECT * FROM #TempTable;
END TRY
BEGIN CATCH
EXECUTE [dbo].[uspPrintError];
END CATCH;
END
I get an error
Invalid object name '#TempTable'
Also not sure if this is the best approach to get data and then update it.
If you absolutely must make that work then I think you'll have to use a global temp table. You'll need to see if it exists before running your dynamic sql and clean up. With a fixed table name you'll run into problems with other connections. Inside the dynamic sql you'll add select * into ##temptable from .... Actually I'm not even sure why you want the temp table in the first place. Can't the dynamic sql just return the results?
On the surface it seems like a solid idea to have one generic procedure for returning data with a couple of parameters to drive it but, without a lot of explanation, it's just not the way database are designed to work.
You should create the temp table.
IF OBJECT_ID('tempdb..##TempTable') IS NOT NULL
DROP TABLE ##TempTable
CREATE TABLE ##TempTable()
I'm creating a SSIS package to load data from a CSV file to SQL table. The sample CSV file is
EMP_ID,EMP_NAME,DEPT_ID,MANAGER_ID,SALARY
1801,SCOTT,20,1221,3000
1802,ALLEN,30,1221,3400
I need to load data into a SQL Server table, but while loading I need to load Department Name and Manager Name instead of their IDs. So I need to convert the CSV source to
1801,SCOTT,FINANCE,JOHNSON,3000
1802,ALLEN,HR,JOHNSON,3400
The values for Department Name and Manager name come from the SQL Server database only. But how do I query and convert ID to text values?
I'm new to SSIS, please suggest how can I achieve this.
Thanks
John
CREATE PROCEDURE [dbo].[BulkInsert]
(
-- Declare Parameters here for your CSV file
)
AS
BEGIN
SET NOCOUNT ON;
declare #query varchar(max)
CREATE TABLE #TEMP
(
[FieldName] [int] NOT NULL ,
[FieldName] int NOT NULL,
)
SET #query = 'BULK INSERT #TEMP FROM ''' + PathOfYourTextFile + ''' WITH ( FIELDTERMINATOR = '','',ROWTERMINATOR = ''\n'')'
--print #query
--return
execute(#query)
BEGIN TRAN;
MERGE TableName AS Target
-- Now here you can get the value Department Name and Manager Name by using Target.Id --in the table from where you mant to get the value of the Manager Name
USING (SELECT * FROM #TEMP) AS Source
ON (Target.YourTableId = Source.YourTextFileFieldId)
-- In the above line we are checking if the particular row exists in the table(Table1) then update the Table1 if not then insert the new row in Table-1.
WHEN MATCHED THEN
UPDATE SET
Target.SomeId= Source.SomeId
WHEN NOT MATCHED BY TARGET THEN
-- Insert statement
The above code is just an example for you by taking the help from this you can edit in your code. And one more important thing for you, Bulk Insert is one of the great way to save the CSV files. So try to use this..:)
In SSIS package from Data Flow tab use LOOKUP process from the Toolbox. You'll specify the table to get your string values from and which columns to use for the join and the column to substitue your IDs with.