使用Shell脚本生成属性文件和SQL查询的结果

时间:2013-06-26 09:15:40

标签: sql oracle shell plsql formatting

我正在尝试创建这样的属性文件......

firstname=Jon
lastname=Snow
occupation=Nights_Watch
family=Stark

...来自这样的查询...

SELECT 
  a.fname as firstname, 
  a.lname as lastname, 
  b.occ as occupation... 
FROM 
  names a, 
  occupation b, 
  family c... 
WHERE... 

我该怎么做?我知道只将spool用于CSV文件,而这在这里不起作用吗?

shell脚本将拾取这些属性文件以运行自动化任务。我正在使用Oracle DB

5 个答案:

答案 0 :(得分:2)

也许是这样的?

psql -c 'select id, name from test where id = 1' -x -t -A -F = dbname -U dbuser

输出就像:

id=1
name=test1

(有关选项的完整列表:man psql。)

答案 1 :(得分:1)

可以从命令行SQL客户端进行此操作,但是如STTLCU所述,最好让查询以“标准”(如CSV)输出,然后使用shell脚本转换结果。否则,因为您将使用的许多功能不是任何SQL标准的一部分,它们将依赖于数据库服务器和客户端应用程序。将此步骤视为ETL的正面,您可以清理“卸载”的数据,以便对其他应用程序有用。

可以肯定的是,有办法在查询应用程序中构建它:例如如果您使用perl DBI::Shell之类的东西作为您的客户端(允许您使用DBI模块连接到许多不同的服务器),您可以通过各种方式为您的输出添加爵士乐。但是,如果可以将查询输出发送到文本文件并通过awk运行它,那么你可能最好。

话虽如此......这就是Postgresql客户端如何做你想做的事情。请注意,设置格式的命令是不是 SQL,而是特定于客户端。

~/% psql -h 192.168.2.69 -d cropdusting -u stubblejumper
psql (9.2.4, server 8.4.14)
    WARNING: psql version 9.2, server version 8.4.
         Some psql features might not work.
You are now connected to database "cropdusting" as user "stubblejumper".

cropdusting=# \pset border 0 \pset format unaligned \pset t \pset fieldsep =
Border style is 0.
Output format is unaligned.
Showing only tuples.
Field separator is "=".
cropdusting=# select year,wmean_yld from bckwht where year=1997 AND freq > 13 ;
1997=19.9761904762
1997=14.5533333333
1997=17.9942857143
cropdusting=# 

使用psql客户端,\pset命令设置影响查询结果表输出的选项。你可以找出哪个选项正在做什么。如果您想使用SQL客户端执行此操作,请告诉我们它是哪一个或通过手册页阅读有关如何格式化查询输出的提示。

答案 2 :(得分:1)

我的答案非常类似于已针对此问题发布的两个答案,但我尝试解释这些选项,并尝试提供准确的答案。

使用Postgres时,您可以使用psql命令行实用程序来获取预期的输出

psql -F = -A -x -X <other options> -c 'select a.fname as firstname, a.lname as lastname from names as a ... ;'

选项包括:

-F : Use '=' sign as the field separator, instead of the default pipe '|'
-A : Do not align the output; so there is no space between the column header, separator and the column value.
-x : Use expanded output, so column headers are on left (instead of top) and row values are on right.
-X : Do not read $HOME/.psqlrc, as it may contain commands/options that can affect your output.
-c : The SQL command to execute
<other options> : Any other options, such as connection details, database name, etc.

答案 3 :(得分:1)

由于您提到spool,我将假设您正在运行Oracle。这应该产生所需格式的结果,您可以立即spool

SELECT
    'firstname=' || firstname || CHR(10) ||
    'lastname=' || lastname || CHR(10) -- and so on for all fields
FROM your_tables;

对于所有数据库引擎,如果您知道对于新行的正确咒语和字符串连接的语法,则应该可以采用相同的方法。

答案 4 :(得分:1)

您必须选择是否要从shell或PL / SQL维护此类文件。两种解决方案都是可能的,两者都是正确的。

因为Oracle必须从文件中读取和写入,所以我会从数据库端进行读取。

您可以使用UTL_FILE包将数据写入文件。

DECLARE
    fileHandler UTL_FILE.FILE_TYPE;
BEGIN
    fileHandler := UTL_FILE.FOPEN('test_dir', 'test_file.txt', 'W');
    UTL_FILE.PUTF(fileHandler, 'firstname=Jon\n');
    UTL_FILE.PUTF(fileHandler, 'lastname=Snow\n');
    UTL_FILE.PUTF(fileHandler, 'occupation=Nights_Watch\n');
    UTL_FILE.PUTF(fileHandler, 'family=Stark\n');

    UTL_FILE.FCLOSE(fileHandler);
EXCEPTION
    WHEN utl_file.invalid_path THEN
        raise_application_error(-20000, 'ERROR: Invalid PATH FOR file.');
END;

示例来源:http://psoug.org/snippet/Oracle-PL-SQL-UTL_FILE-file-write-to-file-example_538.htm

同时使用Oracle外部表从文件中读取。

CREATE TABLE parameters_table
(
    parameters_coupled VARCHAR2(4000)
)
ORGANIZATION EXTERNAL
(
    TYPE ORACLE_LOADER
    DEFAULT DIRECTORY test_dir
    ACCESS PARAMETERS
    (
        RECORDS DELIMITED BY NEWLINE
        FIELDS
        (
            parameters_coupled VARCHAR2(4000)
        )
    )
    LOCATION ('test_file.txt')
);

此时您可以将数据写入您的表中,该表具有一个具有耦合参数和值的列,即:'firstname = Jon'

您可以通过Oracle阅读

您可以通过任何shell脚本阅读它,因为它是纯文本。

然后这只是一个查询问题,即:

SELECT  MAX(CASE WHEN INSTR(parameters_coupled, 'firstname=')  = 1 THEN REPLACE(parameters_coupled, 'firstname=')  ELSE NULL END) AS firstname
,       MAX(CASE WHEN INSTR(parameters_coupled, 'lastname=')   = 1 THEN REPLACE(parameters_coupled, 'lastname=')   ELSE NULL END) AS lastname
,       MAX(CASE WHEN INSTR(parameters_coupled, 'occupation=') = 1 THEN REPLACE(parameters_coupled, 'occupation=') ELSE NULL END) AS occupation
FROM    parameters_table;