Dynamic Pivot without Null value - pivot

This is a dynamic crosstab query in Northwind database:
DECLARE #COUNTRY NVARCHAR(MAX) ='', #COUNTRY2 NVARCHAR(MAX)
SELECT #COUNTRY = #COUNTRY + QUOTENAME(Country)+', '
FROM Customers
GROUP BY Country
SET #COUNTRY= LEFT(#COUNTRY, LEN(#COUNTRY)-1)
SET #COUNTRY2 = REPLACE(#COUNTRY, ',' , '+')
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = 'SELECT * , '+#COUNTRY2+' AS TOTAL
FROM (SELECT E.EmployeeID, E.LastName,
ISNULL( OD.Quantity, 0)* ISNULL(OD.[UnitPrice],0) QU,
O.ShipCountry AS CO
FROM Orders O JOIN Employees E ON O.EmployeeID = E.EmployeeID
JOIN [dbo].[Order Details] OD ON OD.OrderID = O.OrderID) AS T
PIVOT(SUM(QU) FOR CO IN ('+#COUNTRY+')) AS PVT
ORDER BY 1'
EXEC(#SQL)
I need to change the code in a way that have Null values replaced by 0.

DECLARE #COUNTRY NVARCHAR(MAX) = '' ,
#COUNTRY2 NVARCHAR(MAX);
SELECT #COUNTRY = #COUNTRY + COALESCE(QUOTENAME(Country) + ', ', '')
FROM Customers
WHERE EXISTS ( SELECT *
FROM [Orders] AS [o]
WHERE o.[CustomerID] = Customers.[CustomerID] )
GROUP BY Country;
SET #COUNTRY = LEFT(#COUNTRY, LEN(#COUNTRY) - 1);
SET #COUNTRY2 = REPLACE(#COUNTRY, ',', '+');
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = 'SELECT * , ' + #COUNTRY2 +
' AS TOTAL
FROM (
SELECT oe.EmployeeID, oe.LastName, oe.ShipCountry AS CO,
COALESCE(OD.Quantity * OD.UnitPrice, 0) AS QU
FROM (
SELECT EmployeeID, LastName, ShipCountry
FROM (
SELECT DISTINCT
ShipCountry
FROM Orders
) o ,
Employees
) oe
LEFT JOIN Orders O ON O.EmployeeID = oe.EmployeeID AND
[oe].[ShipCountry] = [O].[ShipCountry]
LEFT JOIN [Order Details] OD ON OD.OrderID = O.OrderID
) AS T
PIVOT(SUM(QU) FOR CO IN (' + #COUNTRY + ')) AS PVT
ORDER BY 1';
EXEC(#SQL);

You need to change the SELECT * to:
SELECT ISNULL(Argentina,0) AS 'Argentina' , INSNULL(Belgium,0) AS 'Belgium' , ....
Ofcourse, you would need to change your dynamic query to reflect the ISNULL functions.
Good Luck

Related

How can I add primary key and foreign key constraints after export data from Azure SQL

I'm using SQL Server Management Studio 19 to migrate data from source database to target database.
I select SQL Server Native Client 11.0 as the Data Source.
For Destination I also use "SQL Server Native Client 11.0" and choose target database as destination.
The data was exported successfully but primary key and foreign key constraints aren't there. What do I missed?
Any help or any suggestions are appreciated. Thank you so much!
There are two ways to export the PK and FK.
Using SSMS to generate the sql script. We just need to select the tables. It will generate a script.sql in your local PC.
We also can write some scripts to export the PK and FK of the User tables manually.
I've created a sql script to export PK and FK from system tables and views.
2.1 We can use the following script to export PK.
select case when colNo = 1 then concat('alter table ',concat(concat(res.schemaName,'.'),res.tableName)) else '' end headerOne,
case when colNo = 1 then concat(concat('add constraint ' , res.PKName),' primary key( ') else '' end headerTwo,
case when colNo = 1 then colName else concat(',',colName) end headerThree,
case when colNo = s2.maxRow then ');' else '' end as headerFour
from (
select s.name as schemaName,i.name as PKName,ov.name as tableName,c.name as colName,k.colid as colNo,k.keyno as indexNO
from
sysindexes i
join sysindexkeys k on i.id = k.id and i.indid = k.indid
join sysobjects o on i.id = o.id
join sys.objects ov on o.id = ov.object_id
join sys.schemas s ON ov.schema_id = s.schema_id
join syscolumns c on i.id=c.id and k.colid = c.colid
where o.xtype = 'U' and exists(select 1 from sysobjects where xtype = 'PK' and name = i.name)
) res
left join
(select schemaName,PKName,tableName,max(rono) as maxRow
from
(
select s.name as schemaName,i.name as PKName,ov.name as tableName,c.name as colName, ROW_NUMBER() OVER (PARTITION BY s.name,i.name,ov.name ORDER BY o.name,k.colid) AS rono
from
sysindexes i
join sysindexkeys k on i.id = k.id and i.indid = k.indid
join sysobjects o on i.id = o.id
join sys.objects ov on o.id = ov.object_id
join sys.schemas s ON ov.schema_id = s.schema_id
join syscolumns c on i.id=c.id and k.colid = c.colid
where o.xtype = 'U' and exists(select 1 from sysobjects where xtype = 'PK' and name = i.name)
) s1
group by schemaName,PKName,tableName
) s2 on res.schemaName = s2.schemaName and res.PKName=s2.PKName and res.tableName=s2.tableName
2.2 Then we can copy the script from SSMS.
2.3 Then we paste the script to query window of the Staging database to execute the script.
2.4 After created PK, in the same way, we can export FK and create them.
select
concat(concat('alter table ',c.CONSTRAINT_SCHEMA),concat('.',fk.TABLE_NAME)),
concat(' add constraint ', c.CONSTRAINT_NAME), --cu.COLUMN_NAME
concat(' foreign key( ',cu.COLUMN_NAME),
concat(concat(') references ',c.CONSTRAINT_SCHEMA),concat('.',pk.TABLE_NAME)),
concat(concat('(',pt.COLUMN_NAME),');')
from
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS c
inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk
on c.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
on c.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu
on c.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
inner join (
select
i1.TABLE_NAME,
i2.COLUMN_NAME
from
INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2
on i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
where
i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
) PT
on pt.TABLE_NAME = pk.TABLE_NAME

Insert the data into the remote table from # temp table in the stored procedure

I have a stored procedure in AZURE SQL database.In that there is a requirement to insert the records into the remote table from #temp table.
As xxxx_table is in the remote database used sp_execute_remote.
below is the scenario:
Create Procedure SP1 parameter1, Parameter2
As
select Distinct B.column1, B.Column2
into #A
from (Query1
Union
Query2) B
if (select count(1) from #A) > 0
Begin
Exec sp_execute_remote #data_source_name = N'Remotedatabase',
#stmt = N'INSERT INTO [dbo].[xxxx_table]
SELECT DISTINCT
'xxx' AS 'column1',
'xxx as 'Column2',
'xxx' AS 'Column3',
'xxx' AS 'Column4',
'xxx' AS Column4
FROM #A A INNER JOIN table1 on A.Column1 = Table1.Column2'
End
)
Getting the syntax error as below:
Incorrect syntax near 'xxx'.
Where am i going wrong? or let me know if there is another way to achieve this.
If you need to dynamically build a string in SQL single-quote the whole sentence, or use 'some text' + 'another text' to concat sentences. If you must add single quote use a double single quote ''
Example:
DECLARE #param1 int;
DECLARE #param1 VARCHAR(10);
SET #param1 = 10;
SET #param2 = 'CCDOS87'
#Stmt = 'SELECT Field1 FROM TableName WHERE Field1 = '
+ CAST(#param1 AS VARCHAR(100))
+ ' AND Field1 = '''
+ param2
+ ''''; <- This is a single '
#stmt = N'INSERT INTO [dbo].[Error_table]
SELECT DISTINCT
xxx AS column1,
xxx as Column2,
xxx AS Column3,
xxx AS Column4,
xxx AS Environment
FROM #A A INNER JOIN table1 on A.Column1 = Table1.Column2'
update
If your tables are in different databases but in the same server use:
INSERT INTO SERVER.SCHEMA.TABLE_NAME
SELECT Something
FROM SERVER.SCHEMA.TABLE_NAME

TSQL String modify

I have a problem with string.
I have a variable #Rights which looks like 'ASD,ZXC,QWE,IOP,JKL'
What I need to do is use this string in
SELECT * FROM dbo.Example
WHERE Rights IN (#Rights)
Problem is that I need to convert:
'ASD,ZXC,QWE,IOP,JKL'
to:
'ASD','ZXC','QWE','IOP','JKL'
How can I do this?
you can create a split function
CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
GO
and after you can convert the string in a temp table
DECLARE #Rights NVARCHAR(128)
SET #Rights = 'ASD,ZXC,QWE,IOP,JKL'
SELECT *
INTO #Temp
FROM dbo.Split(#Rights , ',')
and after you can use it in your query like this
SELECT * FROM dbo.Example
WHERE Rights IN (SELECT Data FROM #Temp)
You can try like this:
DECLARE #xml xml, #str varchar(100), #delimiter varchar(10)
SET #str = 'ASD,ZXC,QWE,IOP,JKL'
SET #delimiter = ','
SET #xml = cast(('<X>'+replace(#str, #delimiter, '</X><X>')+'</X>') as xml)
SELECT C.value('.', 'varchar(10)') as value FROM #xml.nodes('X') as X(C)
SQL DEMO
You can use Dynamic SQL:
LiveDemo
-- sample data
CREATE TABLE #Example(ID INT IDENTITY(1,1), Rights VARCHAR(100));
INSERT INTO #Example VALUES ('ASD'), ('ABC'), ('IOP');
DECLARE #Rights NVARCHAR(MAX) = 'ASD,ZXC,QWE,IOP,JKL';
DECLARE #sql NVARCHAR(MAX) =
N'SELECT *
FROM #Example
WHERE Rights IN (''<placeholder>'')';
SET #sql = REPLACE(#sql, '<placeholder>', REPLACE(#Rights, ',', ''','''));
-- SELECT #sql; -- for debug
EXEC dbo.sp_executesql
#sql;
But you should reconsider using Table Valued Parameter instead.

Exporting stored procedure result to excel

Similar Question may have been asked on this forum regarding exporting stored procedure result to excel file,I've tried few attempts to this but the file does not export to the folder that I expect,Your help is appreciated
Stored Procedure that I created
/****** Object: StoredProcedure [dbo].[Copy_DataDump_SpecificQuery] Script Date: 10/28/2014 15:59:03 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[Copy_DataDump_SpecificQuery]
#SQLScript VARCHAR(MAX)
,#OutPut_Number INT OUTPUT
,#Output_FIleName VARCHAR(MAX) OUTPUT
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN
BEGIN TRY
DECLARE #server Varchar (100)
SET #server = 'MyServerName'
DECLARE #FileName VARCHAR(255)
DECLARE #Date VARCHAR(12)
SELECT #Date = CONVERT(VARCHAR(10),GETDATE(),120)
SET #Output_FIleName = CAST(NEWID() AS VARCHAR(MAX))+ '.xls'
DECLARE #FilePath VARCHAR (4000)
SET #FilePath = '\\ComputerName\Users\MyUserName\Downloads\Exel_File' + #Output_FIleName ;
IF OBJECT_ID('tempDB..##temp_Query', 'U') IS NOT NULL
DROP TABLE ##temp_Query;
----------------------------------------------------------------------------------------------
DECLARE #Query AS VARCHAR(MAX)
DECLARE #FROM_Start INT
SELECT #FROM_Start = CHARINDEX(' FROM ',#SQLScript)
SELECT #Query = SUBSTRING(#SQLScript,0,#FROM_Start) + ' INTO ##temp_Query FROM ' + SUBSTRING(#SQLScript,#FROM_Start+6,LEN(#SQLScript))
PRINT (#Query)
Exec(#Query)
------------------------------------------------------------------------------------------------------------------
DECLARE #dbName VARCHAR (100)
SET #dbName = 'master'
DECLARE #sql VARCHAR (5000)
SET #sql = 'Select * from tempdb.dbo.##temp_Query'
DECLARE #dbName1 VARCHAR (100)
IF OBJECT_ID ('tempDB..##TempExport_Query1','U') is not null
DROP TABLE ##TempExport_Query1
IF OBJECT_ID ('tempDB..##TempExport_Query2','U') is not null
DROP TABLE ##TempExport_Query2
SELECT #dbName1 = #dbName
SELECT #dbName = 'use ' + #dbName + ';'
DECLARE #columnNames VARCHAR (8000), #columnConvert VARCHAR (8000), #tempSQL VARCHAR (8000)
SELECT
#tempSQL = LEFT(#sql, CHARINDEX('from', #sql) - 1) + ' into ##TempExport_Query1 ' +
SUBSTRING(#sql, CHARINDEX('from', #sql) - 1, LEN(#sql))
EXEC (#dbName + #tempSQL)
--SELECT *
--FROM tempdb.INFORMATION_SCHEMA.Columns
--WHERE table_name = '##TempExport_Query1'
SELECT #columnNames = COALESCE(#columnNames + ',', '') + '"' + column_name + '"',
#columnConvert = COALESCE(#columnConvert + ',', '') + 'convert(nvarchar(4000),'
+ '[' + column_name + ']' + CASE
WHEN data_type IN ('datetime', 'smalldatetime') THEN ',121'
WHEN data_type IN ('numeric', 'decimal') THEN ',128'
WHEN data_type IN ('float', 'real', 'money', 'smallmoney') THEN ',2'
WHEN data_type IN ('datetime', 'smalldatetime') THEN ',120' ELSE ''
END + ') as ' + '[' + column_name + ']'
FROM tempdb.INFORMATION_SCHEMA.Columns
WHERE table_name = '##TempExport_Query1'
-- execute select query to insert data and column names into new temp table
SELECT #sql = 'select ' + #columnNames + 'temp##SortID into ##TempExport_Query2 from (select ' + #columnConvert + ',
''2'' as temp##SortID
from ##TempExport_Query1 union all select ''' + REPLACE(#columnNames, ',', ''', ''') + ''',
''1'') t '
EXEC (#sql)
SET #sql = 'bcp " select * from ##TempExport_Query2 ORDER BY temp##SortID " queryout "' + #FilePath +
'" -U uno -P uno -c -T -S ' + #server
EXEC master..xp_cmdshell #sql
SET #OutPut_Number = 1
END TRY
BEGIN CATCH
--DECLARE #ErrorDescription VARCHAR(1000) = 'ERROR - ' + ERROR_MESSAGE()
-- RAISERROR(#ErrorDescription,16,1)
SET #OutPut_Number = 2
--SET #OutPut_Message = ##ERROR
END CATCH
End
Parameters
DECLARE #OutPut_Number INT;
DECLARE #OutPut_Message VARCHAR(1000);
EXECUTE dbo.Copy_DataDump_SpecificQuery 'SELECT O.ID AS SystemNumber
,'' AS ManualNumber
,O.Date AS InvoiceDate
,OT.ID AS CustomerCode
,OT.Name AS CustomerName
,I.ID AS ItemID
,I.Description AS Item
,OL.UnitQty
,OL.FreeQty
,OL.UnitPrice
,OL.GrossValue
,NetSaleValue
,DueDate = ''
,A.ID AS SalesRepCode
,ItemCostPrice = OL.UnitPrice
FROM TxnOrder O
INNER JOIN TxnOrderLine OL ON O.UID = OL.TxnOrderUID AND O.SiteUID = Ol.TxnOrder_SiteUID
INNER JOIN Outlet OT ON O.OutletUID = OT.UID
INNER JOIN Item I ON OL.ItemUID = I.UID
INNER JOIN Agent A ON O.AgentUID = A.UID
WHERE O.mpt_TypeEnum = 1
AND( O.IsPrinted = 1 OR O.mpt_SalesmodelEnum = 2)
--AND O.Date >= #StartDate AND O.Date <= #EndDate
--AND (#DistributorUID IS NULL OR O.DistributorUID = #DistributorUID)
--AND (#AgentUID IS NULL OR O.AgentUID = #AgentUID)'
,#OutPut_Number OUTPUT
,#OutPut_Message OUTPUT
SELECT #OutPut_Message
After I execute I receive the following Output on the SQL Output window
69111E97-BEDE-4BDE-9EBE-C063DB690E9F.xls
I have created the permission for the folder as per below screenshot
This Problem was resolved ,I Logged in to the server via RDP and I executed the SP as per below and it worked out..
DECLARE #OutPut_Number INT;
DECLARE #OutPut_Message VARCHAR(1000);
EXECUTE dbo.Copy_DataDump_SpecificQuery 'SELECT O.ID AS SystemNumber
,O.Date AS InvoiceDate
,OT.ID AS CustomerCode
,OT.Name AS CustomerName
,I.ID AS ItemID
,I.Description AS Item
,OL.UnitQty
,OL.FreeQty
,OL.UnitPrice
,OL.GrossValue
,NetSaleValue
,A.ID AS SalesRepCode
,ItemCostPrice = OL.UnitPrice
FROM TxnOrder O
INNER JOIN TxnOrderLine OL ON O.UID = OL.TxnOrderUID AND O.SiteUID = Ol.TxnOrder_SiteUID
INNER JOIN Outlet OT ON O.OutletUID = OT.UID
INNER JOIN Item I ON OL.ItemUID = I.UID
INNER JOIN Agent A ON O.AgentUID = A.UID
WHERE O.mpt_TypeEnum = 1
AND( O.IsPrinted = 1 OR O.mpt_SalesmodelEnum = 2)'
,#OutPut_Number OUTPUT
,#OutPut_Message OUTPUT
SELECT #OutPut_Message
AND In My select Query I removed the Following Columns
'' AS ManualNumber
DueDate = ''
AND as Im already have the permission to access the server via RDP,I replaced the following path as follows
SET #FilePath = '\\ComputerName\Users\MyUserName\Downloads\Exel_File' + #Output_FIleName
C:\Users\Pathuma\Downloads\Excel
SET #FilePath = '\C:\Users\MyUsername\Downloads\Excel' + #Output_FIleName

Check for a string in a CLOB

i want to search for a string in a CLOB:
some thing like id_name_2569
i get all my IDs i need like this:
select project_line_id as ID
from tbl1
where art_id in (
select art_id
from tbl2
where type = 3
);
and i search in this table:
A1 is a CLOB field
select * from tbl3 where dbms_lob.instr(A1, ID)>0;
obviously it isnt working i know, is here a way i could do this?
something like this should work:
select tbl3.*
from tbl1
inner join tbl2
on tbl2.art_id = tbl1.art_id
inner join tbl3
on tbl3.a1 like '%' || tbl1.project_line_id || '%'
where tbl2.type = 3;
You can use DBMS_LOB.instr directly as a join condition:
SELECT *
FROM (SELECT project_line_id AS ID
FROM tbl1
WHERE art_id IN (SELECT art_id FROM tbl2 WHERE TYPE = 3)) v
JOIN tbl3 ON dbms_lob.instr(tbl3.a1, v.ID) > 0

Resources