I am attempting to create a global temp table based off of a dynamic SQL query. I am using an execute SQL task. Thus far, whenever I execute it, the temp table is not created. Below is my script. I have altered my connection property so that it retains the connection and I set the delay validation to true in the data flow task. When I query for the global temp table, the object doesn't exist.
drop table if exists ##HOCExp
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(ShortLabel)
FROM (SELECT p.ShortLabel FROM dbo.TECHEnumValue AS p
JOIN dbo.CNTHospitalOrClinicExposure AS o
ON p.EnumValue = o.MPLEntityExposureBasis
where p.MyEnumType_ID = 610 and p.ShortLabel <>''
GROUP BY p.ShortLabel) AS x;
SET #sql = N'
SELECT EntityFK, ' + STUFF(#columns, 1, 2, '') + '
into ##HOCExp
FROM
(
SELECT p.ShortLabel
, o.MPLEntityExposureUnit
, concat(o.MyInsuredItemHospitalOrClinic_ClassID
, o.MyInsuredItemHospitalOrClinic_ID) as EntityFK
FROM dbo.TECHEnumValue AS p
INNER JOIN dbo.CNTHospitalOrClinicExposure AS o ON p.EnumValue = o.MPLEntityExposureBasis
where p.EnumValue <>0 and p.MyEnumType_ID = 610 and o.MyInsuredItemHospitalOrClinic_ID <>0
) AS j
PIVOT
(
SUM(MPLEntityExposureUnit) FOR ShortLabel IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
--PRINT #sql;
EXEC sp_executesql #sql;
select * from ##HOCExp
Related
Im new to Stack overflow and SQL and I'm trying to replicate a function in Microsoft Power Query to use in SQL instead.
I know how to Unpivot and keep 1 Column in SQL and then had to reference all the other columns by name to make the unpivot.
Now I need to Keep 3 ID columns and Unpivot the rest of the columns
(This table has 355 columns right now and will change)
Can anyone help me with this?
This is the furthest I got (Thanks to RAV DBLearning on Youtube), but I cant seem to find a way to Convert the columns types to 1 type.
DECLARE
#SQLSTRING NVARCHAR(MAX),
#COLUMNLIST NVARCHAR(1000) = ''
SELECT
#COLUMNLIST = #COLUMNLIST + QUOTENAME(NAME) + ','
FROM
sys.columns
WHERE
OBJECT_ID = OBJECT_ID('xp.XPROPERTYVALUES') AND
--COLUMN_ID NOT IN(1,2,3)
COLUMN_ID IN(452,453,454)
SELECT
#COLUMNLIST = LEFT(#COLUMNLIST,LEN(#COLUMNLIST)-1)
SET
#SQLSTRING =
'
SELECT
upv.id,
upv.item_id,
upv.itemtype_id,
upv.X_Category,
upv.X_Values
FROM
xp.XPROPERTYVALUES
UNPIVOT
(
X_Values FOR X_Category
IN
(' + #COLUMNLIST + ')
) AS upv
'
PRINT
(#SQLSTRING)
EXECUTE
sp_executesql #SQLSTRING
It just needs a source query.
And you can re-use the calculated column list for that.
DECLARE #SQLSTRING NVARCHAR(MAX),
#COLUMNLIST NVARCHAR(MAX);
DECLARE #TABLENAME VARCHAR(30) = 'xp.XPROPERTYVALUES';
SELECT #COLUMNLIST = CONCAT(#COLUMNLIST + ', ', QUOTENAME(NAME))
FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID(#TABLENAME)
AND LOWER(NAME) NOT LIKE '%id';
SET #SQLSTRING = N'SELECT upv.id
, upv.item_id, upv.itemtype_id
, upv.X_Category, upv.X_Values
FROM
(
SELECT id, item_id, itemtype_id,
'+ #COLUMNLIST + N'
FROM '+ #TABLENAME +N'
) src
UNPIVOT
(
X_Values FOR X_Category IN (' + #COLUMNLIST + N')
) upv';
-- SELECT #SQLSTRING;
EXECUTE sp_executesql #SQLSTRING;
db<>fiddle here
In sql server I have a table with id. I pass id through openquery in a loop.
while #coun < 1000
begin
select #id=id from #temp where num = #coun
#sql = 'select * from tableoracle where id=' + #id
execute('insert into #temp2 select * from openquery(ORAC, ' + #sql+')')
set #coun = #coun + 1
End
Can I send the id immediately as a set and not one by one?
if you access the entire table at once in oracle without id, the request hangs,
a lot of data
found the solution
declare #a varchar(max) = (select '(' + stuff (
(SELECT ',''' +id + ''''
FROM #temp
for xml path('')),
1, 1, '') + ')')
#sql = 'select * from tableoracle where id in ' + #a
execute('insert into #temp2 select * from openquery(ORAC, ' + #sql+')')
Is there a way to generate dynamic sql statement, such that the field value from one table participates in a table name being joined?
Here is what I am trying to do:
DECLARE #sql NVARCHAR(MAX) = N''
DECLARE #MainProc NVARCHAR(MAX) = N'dbo.MainProc'
SET #sql += N'SELECT ref.*
FROM sys.dm_sql_referenced_entities (' + #MainProc + N', ''OBJECT'') AS ref
INNER JOIN ' + ref.referenced_database_name + '.sys.objects AS o ON ref.referenced_id = o.object_id AND o.type = ''P''
WHERE ref.referenced_schema_name NOT IN (''system'')'
EXEC sp_executesql #sql
How can the value of ref.referenced_database_name be attached to sys.objects?
Yes with a little refactoring. In your original example you were trying to extract a value from dm_sql_referenced_entities before you had queried it.
DECLARE #sql NVARCHAR(MAX) = N''
DECLARE #MainProc NVARCHAR(MAX) = N'Fact.Account_Load'
/* Builds the sys.Objects query.
* Can return multiple queries.
*/
SELECT
#sql +=
'
SELECT
s.*
FROM
' + QUOTENAME(ref.referenced_database_name) + '.sys.objects AS s
WHERE
s.Object_Id = ' + CAST(ref.referenced_id AS VARCHAR(255)) + '
AND s.Type = ''P''
;
'
FROM
sys.dm_sql_referenced_entities('Fact.Account_Load', 'OBJECT') AS ref
WHERE
ref.referenced_database_name IS NOT NULL
GROUP BY
ref.referenced_database_name,
ref.referenced_id
;
-- Executes dynamic query.
EXECUTE(#sql);
I have a stored procedure that dynamically creates a pivot query.
The procedure works and returns the correct data.
Now I have a requirement to show this data in a reporting system that can only pull from a table or view. Since you can not create a dynamic query in a view I tried to do a select from using openquery.
Example '
Select * from OpenQuery([MyServername], 'Exec
Instance.Schema.StoredProcedure')
I get the error back
"the linked server indicates the object has no columns".
I assume this is because of the first select statement that is stuffing the variable with column names.
CODE FROM PROCEDURE
ALTER PROCEDURE [dbo].[FuelCombustorMatrix]
AS
BEGIN
-- Use Master
SET NOCOUNT ON
Declare #cols nvarchar(2000),
#Tcols nvarchar(2000),
#Sql nvarchar (max)
select #cols = stuff ((
Select distinct '], ['+ModelName + ' ' + CombustorName
from CombustorFuel cf
join Model m on cf.modelid = m.modelid
join Combustors cb on cf.CombustorID = cb.CombustorID
where cf.CombustorID > 0
for XML Path('')
),1,2,'')+']'
Set #Tcols = replace(#Cols, ']', '] int')
--Print #Tcols
--Print #Cols
Set #Sql = 'Select GasLiquid, FuelType, '+ #Cols +'
from
(
Select GasLiquid, FuelType, ModelName+ '' '' +CombustorName ModelCombustor, CombFuelStatus+''- ''+CombFuelNote CombFuelStatusNote
from Frames f
join Family fa on f.Frameid = fa.frameid
join Model m on fa.FamilyID = m.FamilyID
join CombustorFuel cf on m.Modelid = cf.modelid
Join Combustors c on cf.CombustorId = c.CombustorID
join FuelTypes ft on cf.FuelTypeID = ft.FuelTypeID
where cf.CombustorFuelID > 0
and CombustorName <> ''''
) up
Pivot
(max(CombFuelStatusNote) for ModelCombustor in ('+ #Cols +')) as pvt
order by FuelType'
exec (#Sql)
END
I am using SQL Server 2008. I use to take the script of my data from SQL table using Tasks --> Generate Scripts option.
Here is my problem:
Let's say I have 21,000 records in Employee table. When I take the script of this table, it takes the insert script for all 21000 records. What is the solution if I want to take only the script of 18000 records from the table?
Is there any solution using SQL query or from the tasks wizard?
Thanks in advance...
Create a new View where you select your desired rows from your Employee table e.g. SELECT TOP 21000...
Then simply script that View instead of the Table.
In case the views are not an option for you I wrote the following code based on the Aaron Bertrand's answer here that will give the insert statement for a single record in the db.
CREATE PROCEDURE dbo.GenerateSingleInsert
#table NVARCHAR(511), -- expects schema.table notation
#pk_column SYSNAME, -- column that is primary key
#pk_value NVARCHAR(10) -- change data type accordingly
AS
BEGIN
SET NOCOUNT ON;
DECLARE #cols NVARCHAR(MAX), #vals NVARCHAR(MAX),
#valOut NVARCHAR(MAX), #valSQL NVARCHAR(MAX);
SELECT #cols = N'', #vals = N'';
SELECT #cols = #cols + ',' + QUOTENAME(name),
#vals = #vals + ' + '','' + ' + 'ISNULL('+REPLICATE(CHAR(39),4)+'+RTRIM(' +
CASE WHEN system_type_id IN (40,41,42,43,58,61) -- dateteime and time stamp type
THEN
'CONVERT(CHAR(8), ' + QUOTENAME(name) + ', 112) + '' ''+ CONVERT(CHAR(14), ' + QUOTENAME(name) + ', 14)'
WHEN system_type_id IN (35) -- text type
THEN
'REPLACE(CAST(' + QUOTENAME(name) + 'as nvarchar(MAX)),'+REPLICATE(CHAR(39),4)+','+REPLICATE(CHAR(39),6)+')'
ELSE
'REPLACE(' + QUOTENAME(name) + ','+REPLICATE(CHAR(39),4)+','+REPLICATE(CHAR(39),6)+')'
END
+ ')+' + REPLICATE(CHAR(39),4) + ',''null'') + '
FROM sys.columns WHERE [object_id] = OBJECT_ID(#table)
AND system_type_id <> 189 -- can't insert rowversion
AND is_computed = 0; -- can't insert computed columns
SELECT #cols = STUFF(#cols, 1, 1, ''),
#vals = REPLICATE(CHAR(39),2) + STUFF(#vals, 1, 6, '') + REPLICATE(CHAR(39),2) ;
SELECT #valSQL = N'SELECT #valOut = ' + #vals + ' FROM ' + #table + ' WHERE '
+ QUOTENAME(#pk_column) + ' = ''' + RTRIM(#pk_value) + ''';';
EXEC sp_executesql #valSQL, N'#valOut NVARCHAR(MAX) OUTPUT', #valOut OUTPUT;
SELECT SQL = 'INSERT ' + #table + '(' + #cols + ') SELECT ' + #valOut;
END
I took the above code and wrapped it the following proc that will use the where clause you give it to select which insert statements to create
CREATE PROCEDURE dbo.GenerateInserts
#table NVARCHAR(511), -- expects schema.table notation
#pk_column SYSNAME, -- column that is primary key
#whereClause NVARCHAR(500) -- the where clause used to parse down the data
AS
BEGIN
declare #temp TABLE ( keyValue nvarchar(10), Pos int );
declare #result TABLE ( insertString nvarchar(MAX) );
declare #query NVARCHAR(MAX)
set #query =
'with qry as
(
SELECT ' + #pk_column + ' as KeyValue, ROW_NUMBER() over(ORDER BY ' + #pk_column + ') Pos
from ' + #table + '
' + #whereClause + '
)
select * from qry'
insert into #temp
exec sp_sqlexec #query
Declare #i int, #key nvarchar(10)
select #i = count(*) from #temp
WHILE #i > 0 BEGIN
select #key = KeyValue from #temp where Pos = #i
insert into #result
exec [dbo].[GenerateSingleInsert] #table, #pk_column, #key
set #i = #i - 1
END
select insertString from #result
END
Calling it could look like the following. You pass in the table name, the table primary key and the where clause and you should end up with your insert statements.
set #whereClause = 'where PrettyColorsId > 1000 and PrettyColorsID < 5000'
exec [dbo].GenerateInserts 'dbo.PrettyColors', 'PrettyColorsID', #whereClause
set #whereClause = 'where Color in (' + #SomeValues + ')'
exec [dbo].GenerateInserts 'dbo.PrettyColors', 'PrettyColorsID', #whereClause