Postgres sql table return statement - sql-server

I got a question related to an translation from SQL Server to Postgres.
I got an table return statement and I don't know how to translate this to Postgres.
my code:
CREATE FUNCTION [dbo].[GetLastUpdatedFluidTreated](#InjectionPoint_ID UNIQUEIDENTIFIER)
RETURNS #Return TABLE (
[RT_FluidTreated_ID] [uniqueidentifier] NOT NULL,
[CL_FluidTreatedType_ID] [uniqueidentifier] NOT NULL,
[Timestamp] [datetime] NULL,
[Last_Updated_Time] [datetime] NULL,
[NewOrModified] [bit] NULL,
[Origin_ID] [uniqueidentifier] NULL,
[IsNew] [bit] NULL
)
AS
BEGIN
INSERT INTO #Return
Select Top 1
x1.[RT_FluidTreated_ID],
x1.[CL_FluidTreatedType_ID],
x1.[Timestamp],
x1.[Last_Updated_Time],
x1.[NewOrModified],
x1.[Origin_ID],
x1.[IsNew]
from RT_FluidTreated x1
WHERE x1.RE_InjectionPoint_ID = #InjectionPoint_ID
Order by x1.[Last_Updated_Time] desc
RETURN;
END
this code above is on sql server.
Can someone help me? thanks

I think a simple set-returning function is what you are looking for:
create function getlastupdatedfluidtreated(p_injectionpoint_id uuid)
returns table (
rt_fluidtreated_id uuid not null,
cl_fluidtreatedtype_id uuid not null,
timestamp timestamp null,
last_updated_time timestamp null,
newormodified boolean null,
origin_id uuid null,
isnew boolean null)
as
$$
select
x1.rt_fluidtreated_id,
x1.cl_fluidtreatedtype_id,
x1.timestamp,
x1.last_updated_time,
x1.newormodified,
x1.origin_id,
x1.isnew
from rt_fluidtreated x1
where x1.re_injectionpoint_id = p_injectionpoint_id
order by x1.last_updated_time desc
limit 1 --<< replaces TOP 1
$$
language sql;
I adjusted the used data types to the most reasonable types in Postgres. You will need to adjust that to the actual types you have used in your table rt_fluidtreated

Related

Convert SQL server to Teradata Query

I want to convert the following SQL server query into a Teradata BTEQ script. Could anyone help in this process..
The table creation logic is as follows and this needs to be converted to Teradata
CREATE TABLE [Eqp].[t_WSTCPEStairstep]
(
[SysID] [smallint] NULL,
[PrinID] [smallint] NULL,
[Account] [bigint] NOT NULL,
[Order_No] [bigint] NOT NULL,
[Order_Typ] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Eqp_Serial] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Eqp_Typ] [varchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Eqp_Model] [varchar] (9) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Disco_Dte] [date] NULL,
[Return_Dte] [date] NULL,
[Restart_Dte] [date] NULL,
[Lost_Dte] [date] NULL,
[TestFlag] [smallint] NULL
) ON [PRIMARY]
WITH
(
DATA_COMPRESSION = PAGE
)
GO
CREATE NONCLUSTERED INDEX [ix_WSTCPEStairstepDiscoDteIndex] ON [Eqp].[t_WSTCPEStairstep] ([Disco_Dte]) ON [PRIMARY]
GO
CREATE CLUSTERED INDEX [ix_WSTCPEStairstepSPAIndex] ON [Eqp].[t_WSTCPEStairstep] ([SysID], [Account]) WITH (DATA_COMPRESSION = PAGE) ON [PRIMARY]
GO
I'm not sure about some of the SQL Server specific bits (compression, clustered, primary), but this will give you a start:
CREATE TABLE Eqp.t_WSTCPEStairstep (
SysID SMALLINT,
PrinID SMALLINT,
Account BIGINT NOT NULL,
Order_No BIGINT NOT NULL,
Order_Typ VARCHAR(1),
Eqp_Serial VARCHAR(25),
Eqp_Typ VARCHAR(2),
Eqp_Model VARCHAR(9) ,
Disco_Dte DATE,
Return_Dte DATE,
Restart_Dte DATE,
Lost_Dte DATE,
TestFlag SNALLINT
)
PRIMARY INDEX(col1, col2, ...);
-- Indexes
CREATE INDEX ix_WSTCPEStairstepDiscoDteIndex (Disco_Dte) ON Eqp.t_WSTCPEStairstep;
CREATE INDEX ix_WSTCPEStairstepSPAIndex (SysID, Account) ON Eqp.t_WSTCPEStairstep;
Which column(s) do you use to access data in this table? If they provide even distribution (i.e. mostly distinct values), then specify these as your PRIMARY INDEX fields. And if these fields are unique, better yet - UNIQUE PRIMARY INDEX. Maybe it's one of the indexes you specified -- disco_dte or (SysID, Account).
Some more notes:
columns should be NULLABLE by default
if TestFlag is just 1/0, you can use the BYTEINT data type
you may want to convert the VARCHAR(1) and VARCHAR(2) to CHAR
for compression, you can add that at multiple levels, but most common I think is at the column level

How to add default constraint with condition in Sql Server?

I am using Sql Server 2014
CREATE TABLE [dbo].[Record](
[RecordId] [int] IDENTITY(1,1) NOT NULL,
[BookId] [int] NULL,
[TopicId] [int] NULL,
[BookName] [varchar](250) NULL,
[TopicName] [varchar](250) NULL,
[RecordPath] [varchar](250) NULL,
[RecordName] [varchar](250) NULL,
[DurationInSec] [float] NULL,
CONSTRAINT [PK_Record] PRIMARY KEY CLUSTERED
(
[RecordId] ASC
)
ALTER TABLE dbo.Record ADD CONSTRAINT DC_RecordPath DEFAULT
(CASE WHEN BookId = 1 THEN 'path/to/1' ELSE RecordPath END)
I want a default constraint with condition as above, but this is not permitted.
Is there any workaround without using triggers?
Edit: Computed column is not working, because the column is filled by a few stored procedures.
I have two conditions;
If BookId is 1 then RecordPath is path 1
Else for any BookId, RecordPath is RecordPath comes from stored procedure
This is what you need if you need that to check only the record with BookId = 1
CHECK (BookId = 1 AND RecordPath = 'path/to/1') OR (BookId != 1)
Esentialy this says: If BookId equals to 1, then the path has to be the one specified, or the BookId can be anything else and for those records the record path can be anything.
RecordPath = RecordPath is not necessary for the second part, since it is always TRUE
Or do you want a computed default?
That is not possible, DEFAULT constraint cannot depend on other columns. To achieve something similar, you'll need a TRIGGER or you can use a computed column or a view instead and use that column/view in your application when reading data.
try this
ALTER TABLE dbo.Record ADD CONSTRAINT DC_RecordPath
CHECK ((CASE WHEN BookId = 1 THEN 'path/to/1' ELSE 'path/to/2' END)=RecordPath)

how to make procedure insert

Please help, how to correct this procedure??
Right now, I'm getting an error:
Implicit conversion from data type varchar to varbinary(max) is not allowed. Use the CONVERT function to run this query.
Code:
CREATE PROCEDURE SP_FILEUPLOAD
#UID int,
#APPCODE varchar(50) = NULL ,
#APPEXPIRED datetime = NULL ,
#SIGNIMAGE image = NULL ,
#SIGNFILE varbinary(MAX) = NULL ,
#HEADUID int,
#PRINCIPALFROM money,
#PRINCIPALTO money,
#EXCEPTIONUSER bit,
#LastUpdate datetime
AS
BEGIN
SET NOCOUNT ON
INSERT INTO APPUSERDTL
(UID,
APPCODE,
APPEXPIRED,
SIGNIMAGE,
SIGNFILE,
HEADUID,
PRINCIPALFROM,
PRINCIPALTO,
EXCEPTIONUSER,
LastUpdate)
VALUES('#UID',
'#APPCODE',
'#APPEXPIRED',
'#SIGNIMAGE',
'#SIGNFILE',
'#HEADUID',
'#PRINCIPALFROM',
'#PRINCIPALTO',
'#EXCEPTIONUSER',
'#LastUpdate')
END
GO
Below is the table structure
[dbo].[APPUSERDTL](
[UID] [int] NOT NULL,
[APPCODE] [varchar](50) NULL,
[APPEXPIRED] [datetime] NULL,
[SIGNIMAGE] [image] NULL,
[SIGNFILE] [varbinary](max) NULL,
[HEADUID] [int] NULL,
[PRINCIPALFROM] [money] NOT NULL,
[PRINCIPALTO] [money] NOT NULL,
[EXCEPTIONUSER] [bit] NOT NULL,
[LastUpdate] [datetime] NOT NULL )
It seems you are passing a varchar value to #SIGNFILE parameter.
Please check the value you are passing
eg. You can replicate this issue
declare #test varbinary(max)=''
select #test
Update
Why you are passing with '' to insert statement? It will consider all the values as varchar if you use within quotes. Remove quotes and try
You can do as below
INSERT INTO APPUSERDTL
(UID,
APPCODE,
APPEXPIRED,
SIGNIMAGE,
SIGNFILE,
HEADUID,
PRINCIPALFROM,
PRINCIPALTO,
EXCEPTIONUSER,
LastUpdate)
VALUES(#UID,
#APPCODE,
#APPEXPIRED,
#SIGNIMAGE,
#SIGNFILE,
#HEADUID,
#PRINCIPALFROM,
#PRINCIPALTO,
#EXCEPTIONUSER,
#LastUpdate)
When the SQL Server trying to perform conversion from the empty string ('') to the varbinary(max) the error occurred. The only way to do is to avoid implicit conversion. If you need to convert the empty string to varbinary type, use the cast(#your_variable as varbinary(max)) construction (in the above code where you calling to you SP SP_FILEUPLOAD from).

Convert text to datetime, and select between two dates

I'm trying to get some values between two dates (the 100 last days). However my column is a text-field, formatted: 17.06.2013
SELECT
.....
WHERE Organizations.OrganizationID = '4360'
AND convert(datetime,convert(varchar(10),StatisticsDate),104) BETWEEN
convert(datetime,GETDATE()-100,104) AND convert(datetime,GETDATE(),104)
GROUP BY Groups.Name, GroupStatistics.StatisticsDate
Mssql error:
The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE operator.
Can someone please tell me what I'm doing wrong?
Thank you! :-)
UPDATE:
[GroupStatisticsID] [int] IDENTITY(1,1) NOT NULL,
[GroupID] [int] NOT NULL,
[CreateUser] [nvarchar](max) NULL,
[StatisticsDate] [text] NULL,
[memberAttendants] [int] NOT NULL,
[Free] [int] NULL,
[FreeHours] [int] NULL,
[GroupName] [text] NULL,
[GroupNumber] [int] NULL,
[Ser] [text] NULL,
[SerNmbr] [int] NULL,
[SerName] [text] NULL
UPDATE2:
I tried SELECT GETDATE() which gave me: 2013-06-18 22:38:25:270
Does that mean I need to convert to this formatting to use BETWEEN?
The date comparision with between is not the problem in your case, since you casted already.
You will have to Group with Not text values:
GROUP BY Name, convert(datetime,convert(varchar(10),StatisticsDate),104)

AFTER INSERT trigger fails when more than one row to be updated

Long time reader, first time caller, and all that...
Here's the business problem: a user makes one or more requests for documents. At some later time, a document is uploaded to the system. If that document matches one or more of the requests, the document request is fulfilled. So, there could be one or many requests for Document A, for instance. When Document A is uploaded, all of the requests for Document A are fulfilled.
And here's my technical problem: I've got an AFTER INSERT trigger on the table where the upload of the document is recorded. It checks the DocumentRequest table and updates each row that matches the uploaded document. If only one row matches (only one request for Document A), everything is hunky-dory. If, however, more than one matches, the UPDATE statement in the trigger fails -- I see this error:
Subquery returned more than 1 value.
This is not permitted when the
subquery follows =, !=, <, <= , >, >=
or when the subquery is used as an
expression.
Here are the CREATE statements for the relevant tables:
CREATE TABLE [dbo].[DocumentRequest](
[DocumentRequestId] [int] IDENTITY(1,1) NOT NULL,
[BatchID] [int] NULL,
[CertificateNum] [varchar](20) NOT NULL,
[RequestedTypCd] [varchar](5) NULL,
[RequestedReason] [varchar](60) NULL,
[DestinationTypCd] [varchar](5) NULL,
[DocumentPackageTypCd] [varchar](5) NULL,
[RequestedDtm] [datetime] NOT NULL,
[RequestNotes] [varchar](1000) NULL,
[RequestStatusTypCd] [varchar](5) NOT NULL,
[InactiveFlag] [char](1) NULL,
[CreationDtm] [datetime] NOT NULL,
[CreationUserID] [varchar](10) NOT NULL,
[CompletedDtm] [datetime] NULL,
[CompletedUserID] [varchar](10) NULL,
[ModifiedDtm] [datetime] NULL,
[ModifiedUserID] [varchar](10) NULL,
CONSTRAINT [XPKDocumentRequest] PRIMARY KEY NONCLUSTERED
(
[DocumentRequestId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
--------------
CREATE TABLE [dbo].[DocumentRequestContents](
[DocumentTypCd] [varchar](5) NOT NULL,
[CreationDtm] [datetime] NOT NULL,
[CreationUserID] [varchar](10) NOT NULL,
[DocumentRequestId] [int] NOT NULL,
[DocumentReceivedDtm] [datetime] NULL,
[DocumentReceivedFlag] [char](1) NULL,
[DocumentIgnoreFlag] [char](1) NULL,
CONSTRAINT [XPKDocumentRequestContents] PRIMARY KEY NONCLUSTERED
(
[DocumentRequestId] ASC,
[DocumentTypCd] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
--------------
CREATE TABLE [dbo].[DocumentStorage](
[DocumentStorageID] [int] IDENTITY(1,1) NOT NULL,
[CertificateNum] [varchar](10) NULL,
[DocumentHandleID] [int] NULL,
[DocumentTypVal] [varchar](100) NULL,
[CreationDtm] [datetime] NULL,
[CreationUserID] [varchar](10) NULL,
[lastupd_user] [varchar](8) NULL,
[lastupd_stamp] [datetime] NULL,
[DocumentNam] [varchar](100) NULL,
PRIMARY KEY NONCLUSTERED
(
[DocumentStorageID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
--------------
CREATE TABLE [dbo].[DocumentProfile](
[DocumentProfileID] [int] IDENTITY(1,1) NOT NULL,
[DocumentTypCd] [varchar](5) NULL,
[DocumentVersionNum] [varchar](10) NULL,
[DocumentApproveInd] [varchar](1) NULL,
[CreationDtm] [datetime] NULL,
[CreationUserID] [varchar](10) NULL,
[lastupd_stamp] [datetime] NULL,
[lastupd_user] [varchar](8) NULL,
[DocumentStorageTypVal] [varchar](100) NULL,
[MIMETypVal] [varchar](50) NULL,
[DocumentSourceTypCd] [varchar](5) NULL,
[DocumentFormatTypCd] [varchar](5) NULL,
[DocumentReceiveLocationTypCd] [varchar](5) NULL,
[DocumentIndexTypCd] [varchar](5) NULL,
[DocumentNam] [varchar](100) NULL,
[DocumentTrackedInd] [char](1) NULL CONSTRAINT [DF_DocumentProfile_DocumentTrackedInd] DEFAULT ('N'),
PRIMARY KEY NONCLUSTERED
(
[DocumentProfileID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
And the trigger...
CREATE TRIGGER [trg_DMTDocumentReceived_DocumentStorage]
ON [dbo].[DocumentStorage]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE DocumentRequestContents
SET DocumentRequestContents.DocumentReceivedFlag = 'Y',
DocumentRequestContents.DocumentReceivedDtm = getdate()
FROM
DocumentRequestContents
INNER JOIN DocumentRequest
ON DocumentRequestContents.DocumentRequestId = DocumentRequest.DocumentRequestId
INNER JOIN DocumentProfile
ON DocumentRequestContents.DocumentTypCd = DocumentProfile.DocumentTypCd
INNER JOIN Inserted
ON DocumentProfile.DocumentStorageTypVal = Inserted.DocumentTypVal
WHERE
(DocumentRequestContents.DocumentReceivedFlag <> 'Y' OR
DocumentRequestContents.DocumentReceivedFlag IS NULL)
AND (DocumentRequest.InactiveFlag IS NULL)
AND (DocumentRequest.CertificateNum = Inserted.CertificateNum)
AND (DocumentProfile.DocumentStorageTypVal = Inserted.DocumentTypVal)
END
I'm at a bit of a loss as to where to go from here. Can you give a guy a hand?
EDIT:
A request can have more than one document, so the table that is being updated in the trigger (DocumentRequestContents) also has a trigger on it, which determines if the entire request has been fulfilled. As far as I can tell, it does not have a subquery, either, but here it is:
CREATE TRIGGER [trg_DMTDocumentReceived_CompletenessCheck]
ON [dbo].[DocumentRequestContents]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #TotalDocs int, #ReceivedDocs int
IF UPDATE(DocumentReceivedFlag)
BEGIN
IF (SELECT DocumentReceivedFlag FROM Inserted) = 'Y' AND (SELECT DocumentReceivedFlag FROM Deleted) = 'N'
BEGIN
SELECT #TotalDocs = count(*)
FROM DocumentRequestContents
INNER JOIN Inserted
ON DocumentRequestContents.DocumentRequestID = Inserted.DocumentRequestID
WHERE (DocumentRequestContents.DocumentIgnoreFlag <> 'Y' OR DocumentRequestContents.DocumentIgnoreFlag IS NULL)
SELECT #ReceivedDocs = count(*)
FROM DocumentRequestContents
INNER JOIN Inserted
ON DocumentRequestContents.DocumentRequestID = Inserted.DocumentRequestID
WHERE DocumentRequestContents.DocumentReceivedFlag = 'Y'
IF (#ReceivedDocs = #TotalDocs)
BEGIN
UPDATE DocumentRequest
SET RequestStatusTypCd = 'CMPLT',
CompletedDtm = getdate(),
CompletedUserID = 'SYSTEM',
ModifiedDtm = getdate(),
ModifiedUserID = 'SYSTEM'
FROM DocumentRequest
INNER JOIN Inserted
ON DocumentRequest.DocumentRequestId = Inserted.DocumentRequestId
END
END
END
END
Thanks,
Jason
The offending line appears to be here:
IF (SELECT DocumentReceivedFlag FROM Inserted) = 'Y' AND
(SELECT DocumentReceivedFlag FROM Deleted) = 'N' ...
This is essentially a "subquery". The IF statement is written with the expectation that there will only be one row in both inserted and deleted. Without knowing the details of what the business logic is here, I can only speculate, but most likely you'll be OK if you just rewrite that as:
IF EXISTS(SELECT 1 FROM inserted WHERE DocumentReceivedFlag = 'Y') AND
EXISTS(SELECT 1 FROM deleted WHERE DocumentReceivedFlag = 'N'))
But it might be more complicated than that... it could be that you actually need to join the inserted to deleted rows and check if the flag has actually changed from 'Y' to 'N'.
Check if you don't have a trigger on DocumentRequestContents as well.
On re-reading, the obvious problem is this part of the second trigger:
IF (SELECT DocumentReceivedFlag FROM Inserted) = 'Y'
AND (SELECT DocumentReceivedFlag FROM Deleted) = 'N'
This would fail if multiple rows where inserted, because SQL Server expects both of these subqueries to return one or no rows.
By the way, I personally avoid triggers at any cost. They introduce too much complexity for me to handle.
You may want to try aliasing the Inserted table in your join. While I haven't experienced this myself, it may be attempting to perform a subquery in your WHERE clause rather than using the joined table.
Your trigger doesn't appear to have a sub-query anywhere in it - this is the only trigger on your table? This error isn't caused by a join or a multi-row update, so I'm at a loss as to why your trigger would be generating this error.
Do you get the error when you're attempting the insert into the table itself? Perhaps it's actually the query you're using to insert that's failing - please post that insert statement as well.

Resources