PL/SQL missing right parenthesis - sql

Hey folks im getting a sql error all the way at the bottom
right before the execute statement at the end of the code block:
stmt := v_first_sql || stmt || v_order_by_sql || v_last_sql;
any ideas of what Im doing wrong?
thanks
FUNCTION search_data
(
p_start_ind IN NUMBER,
p_end_ind IN NUMBER,
p_cols_sort_by IN char_tab,
p_sort_orders IN char_tab,
p_sor_number IN VARCHAR2,
p_tcn IN VARCHAR2,
p_sock IN NUMBER,
p_work_id IN NUMBER,
p_sap in NUMBER
)
RETURN bean_list
IS
stmt VARCHAR2(4000);
result bean_list;
v_jp_ids VARCHAR2(50);
v_first_sql VARCHAR2(512);
v_row_count NUMBER;
BEGIN
v_row_count := p_end_index - p_start_index + 1;
v_first_sql := 'BEGIN ';
v_first_sql := v_first_sql || ' SELECT item_search( id, mwslin,sor_code, fyear, wyear,';
v_first_sql := v_first_sql || ' sock, tcn, non, nomen,sap';
v_first_sql := v_first_sql || ' row_count )';
v_first_sql := v_first_sql || ' BULK COLLECT INTO :bind_var1';
v_first_sql := v_first_sql || ' FROM';
v_first_sql := v_first_sql || ' (';
v_first_sql := v_first_sql || ' SELECT /*+ FIRST_ROWS(' || TO_CHAR(v_row_count) || ') */ ';
v_first_sql := v_first_sql || ' ROWNUM rnum, a.*';
v_first_sql := v_first_sql || ' FROM';
v_first_sql := v_first_sql || ' (';
v_first_sql := v_first_sql || ' SELECT ob.*, COUNT(*) OVER () AS row_count';
v_first_sql := v_first_sql || ' FROM';
v_first_sql := v_first_sql || ' (';
v_order_by_sql := ' ) ob ' || temp_pkg.get_number_by( p_columns_sort_by, p_sort_orders );
v_last_sql := ' ) a';
v_last_sql := v_last_sql || ' WHERE rownum <= ' || TO_CHAR(p_end_index);
v_last_sql := v_last_sql || ' )';
v_last_sql := v_last_sql || ' WHERE rnum >= ' || TO_CHAR(p_start_index);
v_last_sql := v_last_sql || ' ORDER BY rnum;';
v_last_sql := v_last_sql || ' END;';
stmt := v_first_sql || stmt
EXECUTE IMMEDIATE stmt USING OUT result;
RETURN result;
END search_data;

The parentheses in YOUR code appear to be balanced, so clearly the problem is in the text introduced by
temp_pkg.get_order_by( p_columns_sort_by, p_sort_orders )
This function must be returning unbalanced parens.
By the way, unless you've gone to great lengths to sanitize the input, this is a SQL injection attack waiting to happen.

Related

Print a json structure from a dynamic query

I want to create function that return a CLOB with a json content.
But first i want to print the result (see query code) to see how it looks like.
The result must be a json, that will contain the information for 1 record just, this record select query, must be created dynamically.
So I try the next query, to resolve this problem. but i get an error.
Query
declare
v_stmt VARCHAR2(1000);
l_sep varchar2(1) := chr(10);
l_tab varchar2(1) := chr(9);
up_column VARCHAR2(50);
low_column VARCHAR2(50);
cur_asc SYS_REFCURSOR;
Vcdogcur SYS_REFCURSOR;
id_ccd number;
first boolean := true;
begin
id_ccd := 174;
v_stmt := 'select ';
open cur_asc for
SELECT column_name as up_column
,lower(column_name) as low_column
FROM USER_TAB_COLUMNS
WHERE table_name = upper('my_table');
loop
FETCH cur_asc
INTO up_column, low_column;
EXIT WHEN cur_asc%NOTFOUND;
if not first then
v_stmt := v_stmt || ',';
end if;
first := false;
v_stmt := v_stmt || l_sep || l_tab ||up_column || ' as ' || low_column;
END LOOP;
--v_stmt := v_stmt || l_sep || 'from my_table' || l_sep ||'where id = ' || id_ccd || ';';
v_stmt := v_stmt || l_sep || 'from my_table' || l_sep ||'where id = ' || id_ccd;
DBMS_OUTPUT.PUT_LINE('salida: ' || v_stmt);
CLOSE cur_asc;
--v_stmt := v_stmt || l_sep || 'from my_table' || l_sep ||'where id = ' || id_ccd;
--DBMS_OUTPUT.PUT_LINE('salida: ' || v_stmt);
open Vcdogcur for v_stmt;
APEX_JSON.initialize_clob_output;
APEX_JSON.open_object;
APEX_JSON.write('my_table', Vcdogcur);
APEX_JSON.close_object;
DBMS_OUTPUT.put_line(APEX_JSON.get_clob_output);
CLOSE Vcdogcur;
end;
/
DBMS output
salida: select
CREATED as created,
CREATED_BY as created_by,
UPDATED as updated,
UPDATED_BY as updated_by,
ID as id,
TEXT as text,
PART as part,
CODE as code,
DATE as date,
PERCENTAGE as percentage
from my_table
where id = 174
{
"my_table":[
{
"CREATED":"2020-06-04T08:10:09.000000000Z"
,"CREATED_BY":"APEX_APP"
,"UPDATED":"2020-06-04T10:10:09.295632000Z"
,"UPDATED_BY":"APEX_APP"
,"ID":174
,"TEXT":"ALL"
,"PART":2770
,"CODE":2212
,"DATE":"2017-01-01T00:00:00.000000000Z"
,"PERCENTAGE":-4.98
}
]
}
Error
Informe de error -
ORA-01001: cursor no válido
ORA-06512: en línea 44
01001. 00000 - "invalid cursor"
*Cause:
*Action:
Can somebody help me to resolve this?
Best Regards

continuing loops a thing in oracle

I am carrying out another exercise to learn various things about Oracle SQL's syntax today's lesson I've chosen are loops. Please see below code where I am trying to have two fields (temp variables) having values being decreased until it's less than zero depending on which of the variables hit's zero depends on what text I would like to output into the script output. Hopefully it makes sense. If I have made any faux pas's please do shout at me.
DECLARE
"Character" VARCHAR2(255);
"Enemy" VARCHAR2(255);
"Character_Health" NUMBER;
"Enemy_Health" NUMBER;
"Character_Attack" NUMBER;
"Enemy_Attack" NUMBER;
BEGIN -- Generates Base Stats
SELECT 'Hero' INTO "Character" FROM dual;
SELECT 'Villain' INTO "Enemy" FROM dual;
SELECT 100 INTO "Character_Health" FROM dual;
SELECT 25 INTO "Enemy_Health" FROM dual;
SELECT 10 INTO "Character_Attack" FROM dual;
SELECT 5 INTO "Enemy_Attack" FROM dual;
dbms_output.put_line ("Character" || ' (' || "Character_Health" || ') VS ' ||' '|| "Enemy" || ' (' || "Enemy_Health" || ')') ;
dbms_output.put_line ('');
dbms_output.put_line ('FIGHT!');
BEGIN -- Round 1
LOOP
dbms_output.put_line ('');
SELECT "Enemy_Health" - "Character_Attack" INTO "Enemy_Health" FROM dual; -- Hero hits Villain
dbms_output.put_line ("Character" || ' Hits ' || "Enemy" || ' for ' || "Character_Attack" ||' Damage' );
dbms_output.put_line ("Enemy" || ' Has ' || "Enemy_Health" || ' Health Remaining ');
CASE WHEN "Enemy_Health" < 0 THEN dbms_output.put_line ("Enemy" || 'Has Fainted' || "Character" || 'Wins!');
ELSE CONTINUE;
EXIT WHEN "Enemy_Health" < 0;
SELECT "Character_Health" - "Enemy_Attack" INTO "Character_Health" FROM dual; -- Villain hits Hero
dbms_output.put_line ('');
dbms_output.put_line ("Enemy" || ' Hits ' || "Character" || ' for ' || "Enemy_Attack" ||' Damage' );
dbms_output.put_line ("Character" || ' Has ' || "Character_Health" || ' Health Remaining ');
CASE WHEN "Character_Health" < 0 THEN dbms_output.put_line ("Character" || 'Has Fainted' || "Enemy" || 'Wins!');
ELSE CONTINUE;
EXIT WHEN "Character_Health" < 0;
END LOOP;
END;
END;
I found some errors
1. Syntax for case is:
CASE [ expression ]
WHEN condition_1 THEN result_1
WHEN condition_2 THEN result_2
...
WHEN condition_n THEN result_n
[ELSE result]
END CASE
Learn more:
- simple case statement
- searched case statement
CONTINUE stops processing loop and starts it from the begining, so your logic is corrupt - only Hero is attacking.
You need space after "Fainted"
It's better to use IF in this case:
IF "Character_Health" < 0
THEN
dbms_output.put_line ("Character" || 'Has Fainted. ' || "Enemy" || 'Wins!');
EXIT;
END IF;
It's not mistake, but you don't need select into from dual if you want to change value of variable.
Last but not least- i don't like how you use variables. "Character_Health" is similar to 'Character_Health' or '''Character_Health'''. Better use names like characterHealth or character_health.
My version would be something like that:
DECLARE
v_Character VARCHAR2(255) := 'Hero' ;
v_Enemy VARCHAR2(255) := 'Villain';
v_Character_Health NUMBER := 100;
v_Enemy_Health NUMBER := 25;
v_Character_Attack NUMBER := 10;
v_Enemy_Attack NUMBER := 5;
v_nl VARCHAR2(1) := chr(10);
BEGIN
dbms_output.put_line (v_Character || ' (' || v_Character_Health || ') VS ' ||' '|| v_Enemy || ' (' || v_Enemy_Health || ')' || v_nl) ;
dbms_output.put_line ('FIGHT!' || v_nl);
LOOP
v_Enemy_Health := v_Enemy_Health - v_Character_Attack;
dbms_output.put_line (v_Character || ' Hits ' || v_Enemy || ' for ' || v_Character_Attack ||' Damage' );
dbms_output.put_line (v_Enemy || ' Has ' || v_Enemy_Health || ' Health Remaining' || v_nl);
IF v_Enemy_Health < 0 THEN dbms_output.put_line (v_Enemy || 'Has Fainted. ' || v_Character || 'Wins!'); EXIT;
END IF;
v_Character_Health := v_Character_Health - v_Enemy_Attack;
dbms_output.put_line (v_Enemy || ' Hits ' || v_Character || ' for ' || v_Enemy_Attack || ' Damage' );
dbms_output.put_line (v_Character || ' Has ' || v_Character_Health || ' Health Remaining' || v_nl);
IF v_Character_Health < 0 THEN dbms_output.put_line (v_Character || 'Has Fainted. ' || v_Enemy || 'Wins!'); EXIT;
END IF;
END LOOP;
END;
/

debug oracle procedure

I have a oracle stored procedure, inputs is
p_processId = 5660
p_featureClassName ='future_parcels'
p_DrawnGeometry = MDSYS.SDO_GEOMETRY(2003, 2400000, null,
MDSYS.SDO_ELEM_INFO_ARRAY(1, 1003, 1, 27, 2003, 1),
MDSYS.SDO_ORDINATE_ARRAY(8439212.4589933194220066070556640625,
4540074.1191380098462104797363281250, 8439201.7998965308070182800292968750, 4540058.374383729882538318634033203125, 8439315.814959609881043434143066406250, 4540058.374466760084033012390136718750, 8439319.9868115298449993133544921875, 4540067.6362674199044704437255859375, 8439323.231370599940419197082519531250, 4540081.528450479730963706970214843750, 8439328.328618479892611503601074218750, 4540097.737373660318553447723388671875, 8439330.6458750404417514801025390625, 4540129.691041340120136737823486328125, 8439332.959363190457224845886230468750, 4540149.486472180113196372985839843750, 8439227.984901839867234230041503906250, 4540148.055711519904434680938720703125, 8439225.43722324073314666748046875, 4540138.489620880223810672760009765625, 8439223.1199580393731594085693359375, 4540118.576599569991230964660644531250, 8439220.802692830562591552734375, 4540098.663578259758651256561279296875, 8439212.4589933194220066070556640625, 4540074.1191380098462104797363281250, 8439252.6796298995614051818847656250, 4540086.660427900031208992004394531250, 8439243.2996299006044864654541015625, 4540125.440427900291979312896728515625, 8439299.99962989985942840576171875, 4540138.040427899919450283050537109375, 8439310.49962989985942840576171875, 4540098.280427900142967700958251953125, 8439252.6796298995614051818847656250, 4540086.660427900031208992004394531250))
Procedure:
CREATE OR REPLACE
PROCEDURE get_DrawnGeometries (
p_processId IN INTEGER
, p_featureClassName IN VARCHAR2
, p_DrawnGeometry IN SDO_GEOMETRY
, p_prm_val OUT VARCHAR2
)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
CURSOR featClassAttributes_cur (featureClassName IN VARCHAR2) IS
SELECT
gac.id
, lower(gac.column_name) AS column_name
, gac.view_u_pk
, gac.data_type
, gas.naziv
, gat.table_name
FROM geo_atrib_columns gac
JOIN geo_atrib_tables gat ON gat.table_name = gac.table_name
JOIN geo_app_slojevi gas ON gas.naziv = gat.layer_name
WHERE gas.naziv = featureClassName
AND gat.aktivan = 1
AND gac.aktivan = 1
AND gac.view_iu_write = 1
ORDER BY gac.view_order;
vc_sql CLOB;
vc_sql2 CLOB;
vc_sql3 CLOB;
v_columns VARCHAR2(1000);
v_tableName VARCHAR2(1000);
v_whereClause VARCHAR2(1000);
v_whereClause2 VARCHAR2(1000);
v_g_col_name VARCHAR2(30);
v_tolerance VARCHAR2(20);
v_separator VARCHAR2(16) := ' || ''' || glob_var.v_strSeparator || ''' || ';
p_id INTEGER;
v_mssg VARCHAR2(500) := NULL;
BEGIN
vc_sql := 'SELECT #columns# FROM #table_name# WHERE #where_clause#';
vc_sql2 := 'SELECT #columns# FROM #table_name# WHERE #where_clause2#';
vc_sql3 := vc_sql;
FOR rt_att IN featClassAttributes_cur(p_featureClassName) LOOP
IF rt_att.data_type = 'N' THEN
v_columns := v_columns || v_separator || ' nvl(gt_util.num2CharPointSep(' || rt_att.column_name|| '), ''NULL'')';
ELSE
v_columns := v_columns || v_separator || ' nvl(to_char(' || rt_att.column_name|| '), ''NULL'')';
END IF;
IF v_tableName IS NULL THEN
v_tableName := rt_att.table_name;
END IF;
--dbms_output.put_line(v_tableName);
END LOOP;
v_columns := ltrim(v_columns, v_separator);
v_g_col_name := gt_util.get_layer_g_col(v_tableName);
v_tolerance := gt_util.num2CharPointSep(gt_util.get_layer_tollerance(v_tableName, v_g_col_name));
--v_whereClause := 'ins_id = {0} AND SDO_GEOM.RELATE(:geom, ''EQUAL+INSIDE+CONTAINS+COVEREDBY+COVERS+OVERLAPBDYINTERSECT'', ' || v_g_col_name || ', ' || v_tolerance || ') = ''EQUAL+INSIDE+CONTAINS+COVEREDBY+COVERS+OVERLAPBDYINTERSECT''';
v_whereClause := 'ins_id = {0} AND SDO_GEOM.RELATE(:geom, ''EQUAL'', ' || v_g_col_name || ', ' || v_tolerance || ') = ''EQUAL''';
v_whereClause2 := 'ins_id = {0} AND gt_util.geom_is_equal(:geom, ' || v_g_col_name || ', ' || v_tolerance || ') = ''TRUE''';
v_whereClause := replace(v_whereClause, '{0}', to_char(p_processId));
v_whereClause2 := replace(v_whereClause2, '{0}', to_char(p_processId));
vc_sql := replace(vc_sql, '#columns#', v_columns);
vc_sql := replace(vc_sql, '#table_name#', v_tableName);
vc_sql := replace(vc_sql, '#where_clause#', v_whereClause);
vc_sql2 := replace(vc_sql2, '#columns#', v_columns);
vc_sql2 := replace(vc_sql2, '#table_name#', v_tableName);
vc_sql2 := replace(vc_sql2, '#where_clause2#', v_whereClause2);
dbms_output.put_line(vc_sql);
dbms_output.put_line(vc_sql2);
BEGIN
EXECUTE IMMEDIATE vc_sql INTO p_prm_val USING p_DrawnGeometry;
EXCEPTION WHEN NO_DATA_FOUND THEN
EXECUTE IMMEDIATE vc_sql2 INTO p_prm_val USING p_DrawnGeometry;
WHEN TOO_MANY_ROWS THEN
vc_sql3 := replace(vc_sql3, '#columns#', 'id');
vc_sql3 := replace(vc_sql3, '#table_name#', v_tableName);
vc_sql3 := replace(vc_sql3, '#where_clause#', v_whereClause);
vc_sql3 := 'SELECT * FROM (' || vc_sql3 || ' ORDER BY id DESC) WHERE ROWNUM = 1';
EXECUTE IMMEDIATE vc_sql3 INTO p_id USING p_DrawnGeometry;
EXECUTE IMMEDIATE 'DELETE FROM ' || v_tableName || ' WHERE id = ' || p_id;
COMMIT;
v_mssg := 'Identical geometry already exists. Drawn geometry is deleted. If you want to delete new geometry please delete the old one first';
RAISE error_util.ep_UsrExc;
--dbms_output.put_line(vc_sql2);
END;
EXCEPTION WHEN error_util.ep_UsrExc THEN
ERROR_UTIL.log_and_raise(SQLCODE, SQLERRM, v_mssg, DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
RAISE;
END get_DrawnGeometries;
how I can check result and debug it output ?
when I can call it returned errors
Procedure execution failed ORA-06550: line 1, column 233: PLS-00382:
expression is of wrong type ORA-06550: line 1, column 213: PL/SQL:
Statement ignored
In PL/SQL Developer you can right click on procedure name, click test and start debbuging

PL/SQL - Create tables based on cursor using execute immediate?

I've written the following code that selects some student test data and using a cursor, inserts it into a table.
What id like to be able to do is create one table for each student and insert their relative data. This could be one row or multiple rows.
SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE run_student_scores
IS
CURSOR c_pass_fail_cursor
IS
SELECT students.firstname,
test_history.score,
test_id.test_name,
test_id.passing_grade
FROM students
INNER JOIN test_history
ON students.student_id = test_history.student_id
INNER JOIN test_id
ON test_id.test_id = test_history.test_id
WHERE test_history.start_time BETWEEN to_timestamp(sysdate) + INTERVAL '8' HOUR
AND to_timestamp(sysdate) + INTERVAL '21' HOUR;
v_name students.firstname%TYPE;
v_score test_history.score%TYPE;
v_test varchar2(40);
v_passing test_id.passing_grade%TYPE;
v_result varchar2(4);
BEGIN
EXECUTE IMMEDIATE ('create table student_tests_' || (to_char(sysdate, 'yyyymmdd')) || '(student_name VARCHAR2(20), test_name varchar2(40), test_score NUMBER(3), pass_rate NUMBER(3), pass_fail VARCHAR2(4))');
OPEN c_pass_fail_cursor;
LOOP
FETCH c_pass_fail_cursor INTO v_name, v_score, v_test, v_passing;
EXIT WHEN c_pass_fail_cursor%NOTFOUND;
If v_score < v_passing
THEN v_result := 'Fail';
DBMS_OUTPUT.PUT_LINE(v_name || ' ' || v_score || ' ' || v_test || ' ' || V_passing || ' ' || 'Result =' || v_result);
ELSE
v_result := 'Pass';
DBMS_OUTPUT.PUT_LINE(v_name || ' ' || v_score || ' ' || v_test || ' ' || V_passing || ' ' || 'Result =' || v_result);
END IF;
EXECUTE IMMEDIATE 'INSERT INTO student_tests_' || (to_char(sysdate, 'yyyymmdd')) || ' ' || ' values(:1, :2, :3, :4, :5)' using v_name, v_test, v_score, v_passing, v_result;
END LOOP;
CLOSE c_pass_fail_cursor;
END;
/
I've played around with it for the last couple of days and cant get it to work. The closest i can get is to create the tables and insert the first row only, generating an error when the loop tries to create a table that already exists.
Any help would be awesome
Thanks folks
Ben
Outcome: 1 table for each student (unique by name).
The create table ... is now inside the loop surrounded by an exception block. If the table already exists, the exception (ORA-00955) is handled.
SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE run_student_scores
IS
CURSOR c_pass_fail_cursor
IS
SELECT students.firstname,
test_history.score,
test_id.test_name,
test_id.passing_grade
FROM students
INNER JOIN test_history
ON students.student_id = test_history.student_id
INNER JOIN test_id
ON test_id.test_id = test_history.test_id
WHERE test_history.start_time BETWEEN to_timestamp(sysdate) + INTERVAL '8' HOUR
AND to_timestamp(sysdate) + INTERVAL '21' HOUR;
v_name students.firstname%TYPE;
v_score test_history.score%TYPE;
v_test varchar2(40);
v_passing test_id.passing_grade%TYPE;
v_result varchar2(4);
--New variables
table_already_exists EXCEPTION;
PRAGMA EXCEPTION_INIT(table_already_exists, -955);
BEGIN
OPEN c_pass_fail_cursor;
LOOP
FETCH c_pass_fail_cursor INTO v_name, v_score, v_test, v_passing;
EXIT WHEN c_pass_fail_cursor%NOTFOUND;
begin
EXECUTE IMMEDIATE ('create table student_tests_' || v_name || ' (student_name VARCHAR2(20), test_name varchar2(40), test_score NUMBER(3), pass_rate NUMBER(3), pass_fail VARCHAR2(4))');
exception when table_already_exists then
null;
end;
If v_score < v_passing
THEN v_result := 'Fail';
DBMS_OUTPUT.PUT_LINE(v_name || ' ' || v_score || ' ' || v_test || ' ' || V_passing || ' ' || 'Result =' || v_result);
ELSE
v_result := 'Pass';
DBMS_OUTPUT.PUT_LINE(v_name || ' ' || v_score || ' ' || v_test || ' ' || V_passing || ' ' || 'Result =' || v_result);
END IF;
EXECUTE IMMEDIATE 'INSERT INTO student_tests_' || v_name || ' ' || ' values(:1, :2, :3, :4, :5)' using v_name, v_test, v_score, v_passing, v_result;
END LOOP;
CLOSE c_pass_fail_cursor;
END;
/
Grafros answer looks good, but i strongly recommend to take a look at DBMS_ASSERT with DBMS_ASSERT.ENQUOTE_NAME or DBMS_ASSERT.ENQUOTE_LITERAL whenever you have take abitrary strings and use them in execute immidiate.

SQL Server 2008 - Implementing DECODE

First, I know there are plenty of posts etc relating to the use of CASE in place of DECODE, but they don't appear to fit with my concern.
I am trying to convert an Oracle PL/SQL procedure to SQL Server. The procedure builds a SQL statement dynamically, and uses the DECODE function to create a x-tab. The procedure is as so:
PROCEDURE GET_XFORM_DATALOGS (
fLOTCODE IN VARCHAR2,
THEDATA OUT SYS_REFCURSOR) IS
-- VARIABLE DECLARATIONS
TYPE loc_array_type IS TABLE OF VARCHAR2(40); -- array type
loc_array loc_array_type; -- array for test names
prod VARCHAR2(20); -- product ID
step VARCHAR2(20); -- step ID
sql_str VARCHAR2(32000); -- SQL statement
-- EXECUTABLE CODE
BEGIN -- executable part starts here
-- get the test names for the given lot code
SELECT
PT_TESTNAME BULK COLLECT INTO loc_array
FROM
(
SELECT DISTINCT
TESTPARMS.PT_TESTNAME,
TESTPARMS.PT_TESTNUM
FROM
"PRETEST".PRETEST_LOT#PRS_DBLINK LOT,
"PRETEST".PRETEST_MEASURE#PRS_DBLINK MEASURE,
"PRETEST".PRETEST_TEST_PARMS#PRS_DBLINK TESTPARMS
WHERE
LOT.PT_LOTSQ = MEASURE.PT_LOTSQ AND
MEASURE.PT_LOTSQ = TESTPARMS.PT_LOTSQ AND
MEASURE.PT_TESTNUM = TESTPARMS.PT_TESTNUM AND
LOT.PT_LOTID = fLOTCODE
ORDER BY
PT_TESTNUM
);
-- build the SQL string
sql_str := '';
sql_str := sql_str || 'SELECT ';
sql_str := sql_str || ' PRETEST_LOT.PT_LOTID, ';
sql_str := sql_str || ' PRETEST_LOT.PT_LOCTYPE, ' ;
sql_str := sql_str || ' PRETEST_LOT.PT_TESTDATE, ';
sql_str := sql_str || ' PRETEST_MEASURE.PT_WAFERID, ';
sql_str := sql_str || ' PRETEST_MEASURE.PT_XCOORD, ';
sql_str := sql_str || ' PRETEST_MEASURE.PT_YCOORD, ';
-- add the decodes for column headings
FOR i IN loc_array.first..loc_array.last LOOP
sql_str := sql_str || 'max ( decode ( PRETEST_TEST_PARMS.PT_TESTNAME, '''
|| loc_array(i) || ''', PRETEST_MEASURE.PT_MEAS_VALUE, null ) ) '
|| loc_array(i);
IF (i < loc_array.last) THEN
sql_str := sql_str || ', ';
END IF;
END LOOP;
-- build the remainder of the SQL
sql_str := sql_str || ' FROM ';
sql_str := sql_str || ' "PRETEST".PRETEST_LOT#PRS_DBLINK PRETEST_LOT, ';
sql_str := sql_str || ' "PRETEST".PRETEST_MEASURE#PRS_DBLINK PRETEST_MEASURE, ';
sql_str := sql_str || ' "PRETEST".PRETEST_TEST_PARMS#PRS_DBLINK PRETEST_TEST_PARMS ';
sql_str := sql_str || ' WHERE ';
sql_str := sql_str || ' PRETEST_LOT.PT_LOTSQ = PRETEST_MEASURE.PT_LOTSQ AND ';
sql_str := sql_str || ' PRETEST_MEASURE.PT_LOTSQ = PRETEST_TEST_PARMS.PT_LOTSQ AND ';
sql_str := sql_str || ' PRETEST_MEASURE.PT_TESTNUM = PRETEST_TEST_PARMS.PT_TESTNUM AND ';
sql_str := sql_str || ' (PRETEST_LOT.PT_LOTID = :fFLOTCODE) ';
sql_str := sql_str || ' GROUP BY ';
sql_str := sql_str || ' PRETEST_LOT.PT_LOTID, ';
sql_str := sql_str || ' PRETEST_LOT.PT_LOCTYPE, ';
sql_str := sql_str || ' PRETEST_LOT.PT_TESTDATE, ';
sql_str := sql_str || ' PRETEST_MEASURE.PT_WAFERID, ';
sql_str := sql_str || ' PRETEST_MEASURE.PT_XCOORD, ';
sql_str := sql_str || ' PRETEST_MEASURE.PT_YCOORD ';
sql_str := sql_str || ' ORDER BY ';
sql_str := sql_str || ' PRETEST_LOT.PT_TESTDATE ';
-- run the query
OPEN THEDATA FOR sql_str USING fLOTCODE;
END GET_XFORM_DATALOGS;
The question I have is, is this going to be possible to implement in SQL Server? I can't seem to work out how to use CASE WHEN THEN etc to create column headings based on the dynamic data.
Sorry if what I've asked is unclear. Thanks for any help you can offer.
BBz
Well the Oracle equivalent using CASE would be:
sql_str := sql_str || 'max ( CASE WHEN PRETEST_TEST_PARMS.PT_TESTNAME = '''
|| loc_array(i) || ''' THEN PRETEST_MEASURE.PT_MEAS_VALUE END ) '
|| loc_array(i);
So try converting that to SQL Server instead.