2016-05-11 9 views
0

Ich habe eine allgemeine Frage. Ich habe eine Funktion, die eine Datei erstellt. In dieser Funktion kodiere ich derzeit jedoch das Dateinamensmuster basierend auf Argumenteingaben. Jetzt bin ich an einen Punkt gekommen, an dem ich mehr als ein Dateinamensmuster haben muss. Ich habe eine Möglichkeit entwickelt, eine andere Tabelle als Dateinamenkarte zu verwenden, die die Funktion einfach aufrufen kann, wenn der Benutzer diese Dateinamensmuster-ID eingibt. Hier ist mein Beispiel besser zu helfen, meinen Punkt zu illustrieren:Postgres-Funktion - Verwenden von Tabellenzuordnung, um den Wert zu aktualisieren

Hier ist die Erstellung von Tabellen und Dateneinfügung für Referenzzwecke:

create table some_schema.file_mapper(
     mapper_id integer not null, 
     file_name_template varchar); 

    insert into some_schema.file_mapper (mapper_id, file_name_template) 
    values 
    (1, '||v_first_name||''_''||v_last_name||') 
    (2, '||v_last_name||''_''||v_first_name||') 
    (3, '||v_last_name||''_''||v_last_name||'); 

Nun wird die Funktion selbst

create or replace function some_schema.some_function(integer) 

returns varchar as 

$body$ 

Declare 

v_filename_config_id alias for $1; 
v_filename   varchar; 
v_first_name   varchar; 
v_last_name   varchar; 
cmd     text; 

Begin 

v_first_name :='Joe'; 
v_last_name :='Shmoe'; 

cmd := 'select file_name_template 
     from some_schema.file_mapper 
     where mapper_id = '||v_filename_config||''; 
execute cmd into v_filename; 

raise notice 'checking "%"',v_filename; 

return 'done'; 
end; 
$body$ 
LANGUAGE plpgsql; 

Nun, da ich diese haben . Ich möchte Dateinamenmuster mischen und abgleichen können. So zum Beispiel wollte ich mapper_id 3 verwenden, würde ich erwarten, dass eine zurück Datei von „Shmoe_Shmoe.csv“, wenn ich das Skript ausführen:

select from some_schema.some_function(2) 

Das Problem ist, wenn ich es das „v_filename“ Variable lesen es wertet die Werte der Variablen der Funktion nicht aus und gibt sie nicht zurück. Ursprünglich glaubte ich, dass es ein Zitatproblem ist (und es ist wahrscheinlich immer noch so). Nach Messing mit der zitierte ich so weit über den Fehler unten bekommen haben:

ERROR: syntax error at or near "_" 
LINE 4: ...s/dir/someplace/||v_last_name||'_'||v_firs... 
                 ^
QUERY: copy(
      select * 
      from some_schema.some_table) 
      to '/dir/someplace/||v_last_name||'_'||v_first_name||.csv/; 
      DELIMITER, 
      csv HEADER; 
CONTEXT: PL/pgSQL function some_schema.some_function(integer) line 27 at EXECUTE statement 

Wie Sie kann sagen, ist ziemlich viel mir zu sagen, es ist ein Zitat Problem. Gibt es eine Möglichkeit, die Funktion zu erhalten, die Variable richtig auszuwerten und den richtigen Dateinamen zurückzugeben? Lassen Sie es mich wissen, wenn ich nicht klar bin und etwas ausarbeiten muss.

+0

das Format() -Funktion statt der Verkettung von Strings den Befehl zu konstruieren. Dies wird die meisten Ihrer Angebotsprobleme vermeiden. – wildplasser

+0

so etwas wie dieses Beispiel? http://www.postgresql.org/docs/9.1/static/plpgsql-statements.html#PLPGSQL-QUOTE-LITERAL-EXAMPLE –

+0

Ja, knapp über 39.5.5. aber Sie nicht sofort ausgeführt haben, können Sie zuerst tun 'stmt = Format (...);' und führen später den resultierenden String mit 'ausführen stmt;' – wildplasser

Antwort

0

Dies zeigt mehr oder weniger die Verwendung von format(). (Ein wenig reduziert WRT die ursprüngliche Frage):

CREATE TABLE file_mapper 
     (mapper_id INTEGER NOT NULL PRIMARY KEY 
     , file_name_template TEXT 
     ); 
INSERT INTO file_mapper(mapper_id, file_name_template) VALUES (1,'one'), (2, 'two'); 


CREATE OR REPLACE FUNCTION dump_the_shit(INTEGER) 
RETURNS VARCHAR AS 
$body$ 

DECLARE 

v_filename_config_id alias for $1; 
v_filename   VARCHAR; 
name_cmd     TEXT; 
copy_cmd     TEXT; 

BEGIN 

name_cmd := format(e'select file_name_template 
     from file_mapper 
     where mapper_id = %L;', v_filename_config_id); 

EXECUTE name_cmd into v_filename; 
RAISE NOTICE 'V_filename := %', v_filename; 

copy_cmd := format(e'copy(
      select * 
      from %I) 
      to \'/tmp/%s.csv\' 
      csv HEADER;' , 'file_mapper' , v_filename); 

EXECUTE copy_cmd; 

RETURN copy_cmd; 
END; 
$body$ 
LANGUAGE plpgsql; 

SELECT dump_the_shit(1); 

format function description

Zusammenfassung:

  • Verwendung% I für Bezeichner (Tabellennamen und Spaltennamen) [FROM %I]
  • Einsatz % L für Literale wie Abfragekonstanten [WHERE the_date = %L]
  • Gebrauch% s für gewöhnliche Strings [to \'/tmp/%s.csv\']
+0

Alter. Yo, du hast meine beiden Fragen vollständig beantwortet. Mann. Vielen Dank! –

Verwandte Themen