PostgreSQL - How can I pass parameter when I use DO $$? - c#

I am totally new to PostgreSQL and I definitely dislike it but anyway, here I am.
I had this piece of working code where I am simply passing parameters as we "usually" do to my query:
var query = $#"
INSERT INTO TableTwo (
customer_id,
site_id,
item_id,
qoh,
)
SELECT
customer_id,
site_id,
item_id,
qoh
FROM
TableOne
WHERE
customer_id = #Customer_id";
await dbConnection.ExecuteAsync(query, new { Customer_id });
Now I have been asked to add an if statement at the top of the query to check if TableOne exists - I have spent already some time to figure out the syntax but I now got it right ALTHOUGH my parameter is not recognized anymore. This is my current version:
var query = $#"
DO $$
BEGIN
IF EXISTS(SELECT 1
FROM information_schema.tables
WHERE table_schema = CURRENT_SCHEMA AND table_name = 'TableOne'
)
THEN
INSERT INTO TableTwo (
customer_id,
site_id,
item_id,
qoh
)
SELECT
customer_id,
site_id,
item_id,
qoh
FROM
TableOne
WHERE
customer_id = #Customer_id;
END IF;
END
$$;";
await dbConnection.ExecuteAsync(query, new { Customer_id });
So I had to add "DO $$" and a bunch of semicolumn around just to get it to run again but now I am getting the following error: Npgsql.PostgresException: '42883: operator does not exist: # character varying'
I've tried a few more options but I can't get it to work. Can anyone help, please?
Thanks a lot

I've got it working - it is a simple fix that seems like working so far, I have basically used string interpolation rather than passing the parameter.
Here you go and thanks for the help
var query = $#"
DO $$
BEGIN
IF EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema = CURRENT_SCHEMA AND table_name = 'TableOne')
THEN
INSERT INTO TableTwo (
customer_id,
site_id,
item_id,
qoh
)
SELECT
customer_id,
site_id,
item_id,
qoh
FROM
TableOne
WHERE
customer_id = '{Customer_id}';
END IF;
END
$$;";
await dbConnection.ExecuteAsync(query);
Although as #Selvin said - this is not the best solution and apparently it leaves the code open to SQL Injection attack.
Any better ways to do that?

Related

I want the last entries in my Microsoft SQL Server database but get duplication

My problem is that I want to start a database query which should give me the last (maxDate) entry of every Serial number.
I am working with a Microsoft SQL Server database.
The first picture shows all entries in the database:
After I have run the following code I get this output:
string aQuery = #" SELECT *
FROM (
SELECT SerialNumber, MAX(Date) as MaxDate
FROM eBox_Deploy
GROUP BY SerialNumber
) r
INNER JOIN eBox_Deploy t
ON t.SerialNumber = r.SerialNumber AND t.Date = r.MaxDate";
using (var db = new eBoxDataContext())
{
list.AddRange(db.ExecuteQuery<eBox_Deploy>(bQuery));
}
After picture:
Now my problem is that I have duplicates because they already exists in the database. Distinct doesn't work well because these all have different Id´s.
How can I get them away?
You could use windowed functions:
SELECT *
FROM (SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY [SerialNumber] ORDER BY [Date] DESC)
FROM eBox_Deploy) AS sub
WHERE rn = 1;
If your [Date] is not unique within SerialNumber group use RANK() to get ties.

Entity Framework SqlQuery not returning row_number() value

I have a SELECT statement that returns row_number() value with all other fields from table. Query is pretty simple and is working in SSMS:
SELECT
*, CAST(ROW_NUMBER() OVER(ORDER BY TablePrimaryKey) AS INT) AS [RowNumber]
FROM
TableName
WHERE
TablePrimaryKey > 10
(In real application WHERE statement is much more complex, but for simplicity I put it like this)
In my project I created a POCO class that contains RowNumber property (with all other necessary properties)
...
public int RowNumber { get; set; }
...
And I made sure migrations won't create additional columns in table at my entityConfiguration class:
this.Ignore(x => x.RowNumber);
Problem is that with Entity Framework's SqlQuery() method it returns all columns from the table as it should, but RowNumber is always 0. I'm using Entity Framework 6.1 version. Did I miss something, or can this not be done this way?
This is to answer your question in comment.
WITH main AS ( SELECT * ,ROW_NUMBER() OVER(ORDER BY PrimaryKeyId) AS
'RowNumber' FROM [TableName] WHERE [month] = 10 AND [year] = 2014 )
SELECT * FROM main WHERE RowNumber = 2
C#/EF code:
int RowNumber = 2;
var row = TableName.OrderBy(t=>t.PrimaryKeyId).Skip(RowNumber -1).Take(1);
The SQL generated looks like:
DECLARE #p0 Int = 1
DECLARE #p1 Int = 1
SELECT [t1].[ID], [t1].c1 FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID]) AS [ROW_NUMBER],
[t0].[ID], [t0].c1
FROM [TableName] AS [t0]
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN #p0 + 1 AND #p0 + #p1
ORDER BY [t1].[ROW_NUMBER]
I am using Linq-to-SQL, EF should be similar: the sorting is on server side, and it returns 1 record only.

List of Tables names used in MVC Application [duplicate]

I'm looking at creating a basic ORM (purely for fun), and was wondering, is there a way to return the list of tables in a database and also the fields for every table?
Using this, I want to be able to loop through the result set (in C#) and then say for each table in the result set, do this (e.g. use reflection to make a class that will do or contain xyz).
Further to this, what are some good online blogs for SQL Server? I know this question is really about using system SPs and databases in Sql Server, and I am ok with general queries, so I'm interested in some blogs which cover this sort of functionality.
Thanks
Is this what you are looking for:
Using OBJECT CATALOG VIEWS
SELECT T.name AS Table_Name ,
C.name AS Column_Name ,
P.name AS Data_Type ,
C.max_length AS Size ,
CAST(P.precision AS VARCHAR) + '/' + CAST(P.scale AS VARCHAR) AS Precision_Scale
FROM sys.objects AS T
JOIN sys.columns AS C ON T.object_id = C.object_id
JOIN sys.types AS P ON C.system_type_id = P.system_type_id
WHERE T.type_desc = 'USER_TABLE';
Using INFORMATION SCHEMA VIEWS
SELECT TABLE_SCHEMA ,
TABLE_NAME ,
COLUMN_NAME ,
ORDINAL_POSITION ,
COLUMN_DEFAULT ,
DATA_TYPE ,
CHARACTER_MAXIMUM_LENGTH ,
NUMERIC_PRECISION ,
NUMERIC_PRECISION_RADIX ,
NUMERIC_SCALE ,
DATETIME_PRECISION
FROM INFORMATION_SCHEMA.COLUMNS;
Reference : My Blog - http://dbalink.wordpress.com/2008/10/24/querying-the-object-catalog-and-information-schema-views/
Tables ::
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'
columns ::
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
or
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='your_table_name'
Get list of all the tables and the fields in database:
Select *
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_CATALOG Like 'DatabaseName'
Get list of all the fields in table:
Select *
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_CATALOG Like 'DatabaseName' And TABLE_NAME Like 'TableName'
I tested a few solutions an found that
Select *
From INFORMATION_SCHEMA.COLUMNS
gives you the column info for your CURRENT/default database.
Select *
From <DBNAME>.INFORMATION_SCHEMA.COLUMNS
, without the < and >, gives you the column info for the database DBNAME.
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
Your other inbuilt friend here is the system sproc SP_HELP.
sample usage ::
sp_help <MyTableName>
It returns a lot more info than you will really need, but at least 90% of your possible requirements will be catered for.
Just throwing this out there - easy to now copy/paste into a word or google doc:
PRINT '<html><body>'
SET NOCOUNT ON
DECLARE #tableName VARCHAR(30)
DECLARE tableCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT T.name AS TableName
FROM sys.objects AS T
WHERE T.type_desc = 'USER_TABLE'
ORDER BY T.name
OPEN tableCursor
FETCH NEXT FROM tableCursor INTO #tableName
WHILE ##FETCH_STATUS = 0 BEGIN
PRINT '<h2>' + #tableName + '</h2>'
PRINT '<pre>'
SELECT LEFT(C.name, 30) AS ColumnName,
LEFT(ISC.DATA_TYPE, 10) AS DataType,
C.max_length AS Size,
CAST(P.precision AS VARCHAR(4)) + '/' + CAST(P.scale AS VARCHAR(4)) AS PrecScale,
CASE WHEN C.is_nullable = 1 THEN 'Null' ELSE 'No Null' END AS [Nullable],
LEFT(ISNULL(ISC.COLUMN_DEFAULT, ' '), 5) AS [Default],
CASE WHEN C.is_identity = 1 THEN 'Identity' ELSE '' END AS [Identity]
FROM sys.objects AS T
JOIN sys.columns AS C ON T.object_id = C.object_id
JOIN sys.types AS P ON C.system_type_id = P.system_type_id
JOIN INFORMATION_SCHEMA.COLUMNS AS ISC ON T.name = ISC.TABLE_NAME AND C.name = ISC.COLUMN_NAME
WHERE T.type_desc = 'USER_TABLE'
AND T.name = #tableName
ORDER BY T.name, ISC.ORDINAL_POSITION
PRINT '</pre>'
FETCH NEXT FROM tableCursor INTO #tableName
END
CLOSE tableCursor
DEALLOCATE tableCursor
SET NOCOUNT OFF
PRINT '</body></html>'
SELECT * FROM INFORMATION_SCHEMA.COLUMNS for get all
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS for get all table name.
Try it on sqlserver,
This will get you all the user created tables:
select * from sysobjects where xtype='U'
To get the cols:
Select * from Information_Schema.Columns Where Table_Name = 'Insert Table Name Here'
Also, I find http://www.sqlservercentral.com/ to be a pretty good db resource.
This will return the database name, table name, column name and the datatype of the column specified by a database parameter:
declare #database nvarchar(25)
set #database = ''
SELECT cu.table_catalog,cu.VIEW_SCHEMA, cu.VIEW_NAME, cu.TABLE_NAME,
cu.COLUMN_NAME,c.DATA_TYPE,c.character_maximum_length
from INFORMATION_SCHEMA.VIEW_COLUMN_USAGE as cu
JOIN INFORMATION_SCHEMA.COLUMNS as c
on cu.TABLE_SCHEMA = c.TABLE_SCHEMA and c.TABLE_CATALOG =
cu.TABLE_CATALOG
and c.TABLE_NAME = cu.TABLE_NAME
and c.COLUMN_NAME = cu.COLUMN_NAME
where cu.TABLE_CATALOG = #database
order by cu.view_name,c.COLUMN_NAME
For MYSQL:
Select *
From INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA = "<DatabaseName>"
I found an easy way to fetch the details of Tables and columns of a particular DB using SQL developer.
Select *FROM USER_TAB_COLUMNS
in a Microsoft SQL Server you can use this:
declare #sql2 nvarchar(2000)
set #sql2 ='
use ?
if ( db_name(db_id()) not in (''master'',''tempdb'',''model'',''msdb'',''SSISDB'') )
begin
select
db_name() as db,
SS.name as schemaname,
SO.name tablename,
SC.name columnname,
ST.name type,
case when ST.name in (''nvarchar'', ''nchar'')
then convert(varchar(10), ( SC.max_length / 2 ))
when ST.name in (''char'', ''varchar'')
then convert(varchar(10), SC.max_length)
else null
end as length,
case when SC.is_nullable = 0 then ''No'' when SC.is_nullable = 1 then ''Yes'' else null end as nullable,
isnull(SC.column_id,0) as col_number
from sys.objects SO
join sys.schemas SS
on SS.schema_id = SO.schema_id
join sys.columns SC
on SO.object_id = SC.object_id
left join sys.types ST
on SC.user_type_id = ST.user_type_id and SC.system_type_id = ST.system_type_id
where SO.is_ms_shipped = 0
end
'
exec sp_msforeachdb #command1 = #sql2
this shows you all tables and columns ( and their definition ) from all userdefined databases.

Create table and insert rows based on multiple select statements in SQL Server 2008

My situation is after login my website I wanted to show how many employees active, inactive & also for department wise, collage wise employees list of counts.
For that I created a procedure to create temporary table if it is not exist else drop table create temporary table, after that I wrote some SQL queries to get count of employees, department with conditions & then I'm inserting records to table.
Then I need the inserted rows. Now my problem is while executing procedure in SQL it executes but it's not creating & inserting any rows, I don't know why this happens. Please help me if any knows a solution to this problem.
My code:
alter proc SP_TEMPRECORDFORCOUNT
as
begin
IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TEMPRECORDFORCOUNT'))
BEGIN
drop table dbo.TEMPRECORDFORCOUNT
END
create table dbo.TEMPRECORDFORCOUNT(totalemployeecount int,activeemployeecount int,inactiveemployeecount int,deptwiseemployeecount int,activeemployeecount int)
declare #totalemployeecount int
declare #activeemployeecount int
declare #inactiveemployeecount int
declare #deptwiseemployeecount int
declare #activeemployeecount int
select #totalemployeecount =COUNT(*) from Employee
select #activeemployeecount =COUNT(*) from Employee where status=1
select #inactiveemployeecount =COUNT(*) from Employee where status=0
select #deptwiseemployeecount = count(*) from Department where e_id !=null
select #activeemployeecount = count(*) from Department d inner join Employee e on d.e_id =e.e_id where status_id=1
insert into TEMPRECORDFORCOUNT
(
totalemployeecount
,activeemployeecount
,inactiveemployeecount
,deptwiseemployeecount
,activeemployeecount
)
values
(
#totalemployeecount ,
#activeemployeecount ,
#inactiveemployeecount ,
#deptwiseemployeecount ,
#activeemployeecount ,
)
end
is it correct way thing i'm doing? if not please correct me.
With SQL Server 2008 R2 you have the option for table variables.
So your statement should be changed to the following:
DECLARE #TEMPRECORDFORCOUNT TABLE(totalemployeecount int,activeemployeecount int,inactiveemployeecount int,deptwiseemployeecount int,activeemployeecount int)
insert into #TEMPRECORDFORCOUNT
(
totalemployeecount
,activeemployeecount
,inactiveemployeecount
,deptwiseemployeecount
,activeemployeecount
)
values
(
#totalemployeecount ,
#activeemployeecount ,
#inactiveemployeecount ,
#deptwiseemployeecount ,
#activeemployeecount ,
)
SELECT * FROM #TEMPRECORDFORCOUNT
;

Dynamic Where Clause - Some variables not passing

I was wondering if the below scenario will work? I am having trouble with it.
I have a smart tag SQLDataSource with a query like such:
SELECT [col1], [col2], [col3] FROM [Table1] WHERE (#SubType = #SubID) ORDER BY [col1] ASC
No matter where or how I set the #SubType parameter, it does not work, yet if I change the query to WHERE [col1] = #SubID (removing the #SubType) it works fine.
Can I set a parameter as a field name to compare against like my query does?
That's not how parameters work. Parameters are not string replacement. They work with values, not database objects names (Columns, Tables, etc.).
The solution is to first assemble the SQL query with the desired columns (code behind) and then set the parameter's values.
If you want to dynamically replace the items in your WHERE clause then you will want to look at using Dynamic SQL, then you can build your SQL as a string and execute it.
Code sample from http://www.sommarskog.se/dynamic_sql.html
DECLARE #sql nvarchar(2000)
SELECT #sql = 'SELECT O.OrderID, SUM(OD.UnitPrice * OD.Quantity)
FROM dbo.Orders O
JOIN dbo.[Order Details] OD ON O.OrderID = OD.OrderID
WHERE O.OrderDate BETWEEN #from AND #to
AND EXISTS (SELECT *
FROM dbo.[Order Details] OD2
WHERE O.OrderID = OD2.OrderID
AND OD2.ProductID = #prodid)
GROUP BY O.OrderID'
EXEC sp_executesql #sql, N'#from datetime, #to datetime, #prodid int',
'19980201', '19980228', 76
Another helpful link:
Dynamic WHERE Clause

Categories

Resources