views:

151

answers:

1

When we try to create a view within a funcion we get ERROR: there is no parameter $1. This is the sample code.

Begin

CREATE VIEW artikelnr AS
SELECT datum, 'uitgifte' as "type", CASE WHEN 'test'='test' THEN 0 END as "aantal ontvangen", aantal as "aantal uitgegeven"
FROM uitgifteregel 
JOIN artikel ON artikel.artikelnr = new.artikelnr
JOIN uitgifte ON uitgifte.uitgiftenr = uitgifteregel.uitgiftenr

UNION
SELECT datum, 'ontvangst' as "type", aantal as "aantal ontvangen" , CASE WHEN 'test'='test' THEN 0 END as "aantal uitgegeven"
FROM ontvangstregel 
JOIN artikel ON artikel.artikelnr = new.artikelnr
JOIN ontvangst ON ontvangst.ontvangstnr = ontvangstregel.ontvangstnr;
Return new; 
end;

When we replace new.artikelnr on line 7 with value 1 it works like it should, but the function needs to work with different artikelnr's.

example line 7: JOIN artikel ON artikel.artikelnr = new.artikelnr

Please point us in the right direction.

Response: We have to create this view for educational purposes. I have uploaded an image of the view and the tablestructure of our database:

http://img208.imageshack.us/img208/5655/tablesk.jpg

Our first goal was to create a view for one artikel. We achieved this with the following code:

CREATE VIEW artikelmutatiestotaal AS
SELECT null as "datum",'totaal' as "type",sum(ontvangstregel.aantal)as "aantal ontvangen",sum(uitgifteregel.aantal) as "aantal uitgegeven"
FROM uitgifteregel, ontvangstregel
UNION
SELECT datum,'uitgifte' as "type", CASE WHEN 'test'='test' THEN 0 END as "aantal ontvangen", aantal as "aantal uitgegeven"
FROM uitgifteregel 
JOIN artikel ON artikel.artikelnr = 1
JOIN uitgifte ON uitgifte.uitgiftenr = uitgifteregel.uitgiftenr
UNION
SELECT datum,'ontvangst' as "type", aantal as "aantal ontvangen" , CASE WHEN 'test'='test' THEN 0 END as "aantal uitgegeven"
FROM ontvangstregel 
JOIN artikel ON artikel.artikelnr = 1
JOIN ontvangst ON ontvangst.ontvangstnr = ontvangstregel.ontvangstnr

Only thing we can't achieve is to get the value of artikelnr out of our insert statement.

CREATE FUNCTION addview() returns trigger as '
Begin
CREATE VIEW artikelnr AS
SELECT null as "datum",'totaal' as "type",sum(ontvangstregel.aantal)as "aantal ontvangen",sum(uitgifteregel.aantal) as "aantal uitgegeven"
FROM uitgifteregel, ontvangstregel
UNION
SELECT datum,'uitgifte' as "type", CASE WHEN 'test'='test' THEN 0 END as "aantal ontvangen", aantal as "aantal uitgegeven"
FROM uitgifteregel 
JOIN artikel ON artikel.artikelnr = new.artikelnr
JOIN uitgifte ON uitgifte.uitgiftenr = uitgifteregel.uitgiftenr 
UNION
SELECT datum,'ontvangst' as "type", aantal as "aantal ontvangen" , CASE WHEN 'test'='test' THEN 0 END as "aantal uitgegeven"
FROM ontvangstregel 
JOIN artikel ON artikel.artikelnr = artikelnr
JOIN ontvangst ON ontvangst.ontvangstnr = ontvangstregel.ontvangstnr
end;
'language plpgsql;

When we replace JOIN artikel ON artikel.artikelnr = new.artikelnr on line 7 with

JOIN artikel ON artikel.artikelnr = 1 

it works fine. Sorry for posting my question very unstructured. I don't know very good which information is important for answering this question.

A: 

What database is this?

What is this new keyword? Is this code copied from some trigger?

  • Replace new with correct table name in JOIN clause.
  • remove Return new;

If I remember correctly, MsAccess reports similar error when you misspell field name.
Next thing would be to check all field names. Alternatively, use some visual query builder and create those union queries to be sure that all field names are correct.

I think that you can loose those CASE statements and write just 0 AS "Some Fieldname"

Try this. It should work. (I did not test it against database)

CREATE OR REPLACE VIEW artikelnr AS
  SELECT datum, 'uitgifte' as "type", 0 as "aantal ontvangen", 
       aantal as "aantal uitgegeven"
  FROM uitgifteregel 
  JOIN artikel ON artikel.artikelnr = uitgifteregel.artikelnr
  JOIN uitgifte ON uitgifte.uitgiftenr = uitgifteregel.uitgiftenr

UNION
  SELECT datum, 'ontvangst' as "type", aantal as "aantal ontvangen" , 
         0 as "aantal uitgegeven"
  FROM ontvangstregel 
  JOIN artikel ON artikel.artikelnr = ontvangstregel.artikelnr
  JOIN ontvangst ON ontvangst.ontvangstnr = ontvangstregel.ontvangstnr;

Edit:
I don't know much about Postgresql, but you probably should look into EXECUTE SCRIPT - send artikelnr as parameter and then construct DDL for view in script.

Based on my experience with other databases (Oracle and SQL server), I don't think that you should create one view for each record. What are you trying to accomplish with this approach?

If goal is to have precompiled views and this gain execution speed, same thing can probably be achieved with parametrized query. Put it into stored procedure and send artikelnr as parameter.

If it's not for performance reason, can you please explain why are you doing it like this.

Edit 2:
Re answer: You cannot create view that way. Problem is that CREATE VIEW takes statements without replacing values - it tries to create view with new.artikelnr and then it fails because you don't have table new outside of trigger. You need to construct statement as string or as file and then execute that statement. I checked documentation for PostgreSQL and there is EXECUTE command that is used for constructing and executing dynamic commands. Something like this should probably work:

EXECUTE 
  'CREATE OR REPLACE VIEW artikelnr AS '
  || ' SELECT datum, 'uitgifte' as "type", 0 as "aantal ontvangen",' 
  || '    aantal as "aantal uitgegeven" '
  || ' FROM uitgifteregel '
  || ' JOIN artikel ON artikel.artikelnr = ' 
  || new.artikelnr
  || ' JOIN uitgifte ON uitgifte.uitgiftenr = uitgifteregel.uitgiftenr '
  || ' UNION '
  || '   SELECT datum, 'ontvangst' as "type", aantal as "aantal ontvangen" , '
  || '        0 as "aantal uitgegeven" '
  || ' FROM ontvangstregel  '
  || ' JOIN artikel ON artikel.artikelnr = '
  || new.artikelnr
  || ' JOIN ontvangst ON ontvangst.ontvangstnr = ontvangstregel.ontvangstnr; '

This is one giant concat with new.artikelnr value inserted on right places. It "inserts" literal value of artikelnr into SQL code and then you get SQL that is executed via EXECUTE statement.

Please note that above code does not take care about quoting and it definitely will not work as is (since this example is for educational purposes, it is left to reader to correct it as exercise :).

In the documentation for EXECUTE statement you will find examples that use quoting functions which should be used to correctly construct above command.

zendar
Thanks for the quick response. The database we use is postgresql. This piece of code is of a function which will be executedby the following trigger. CREATE TRIGGER addviewAFTER INSERT ON artikel for EACH ROWEXECUTE PROCEDURE addview();The trigger will work when we insert a new artikel.artikelnr is means the same as productnr. artikelnr is the primary key of the artikel table.new.artikelnr references to artikelnr in our insert statement. I hope this clears some things up.
Hi. I have edited the post, because comment leaves too little space to add the information. I hope it is helpfull.
Thanks for helping me. I will look up the documentation and to use the execute statement.